/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const GBEMU_DURATION: number = 0.000020833333110203966;
const GBEMU_0: number = 0;
const GBEMU_1: number = 1;
const GBEMU_2: number = 2;
const GBEMU_3: number = 3;
const GBEMU_4: number = 4;
const GBEMU_5: number = 5;
const GBEMU_6: number = 6;
const GBEMU_7: number = 7;
const GBEMU_8: number = 8;
const GBEMU_9: number = 9;
const GBEMU_10: number = 10;
const GBEMU_11: number = 11;
const GBEMU_12: number = 12;
const GBEMU_13: number = 13;
const GBEMU_14: number = 14;
const GBEMU_15: number = 15;
const GBEMU_16: number = 16;
const GBEMU_17: number = 17;
const GBEMU_18: number = 18;
const GBEMU_19: number = 19;
const GBEMU_20: number = 20;
const GBEMU_21: number = 21;
const GBEMU_22: number = 22;
const GBEMU_23: number = 23;
const GBEMU_24: number = 24;
const GBEMU_25: number = 25;
const GBEMU_26: number = 26;
const GBEMU_27: number = 27;
const GBEMU_28: number = 28;
const GBEMU_29: number = 29;
const GBEMU_30: number = 30;
const GBEMU_31: number = 31;
const GBEMU_32: number = 32;
const GBEMU_33: number = 33;
const GBEMU_34: number = 34;
const GBEMU_35: number = 35;
const GBEMU_36: number = 36;
const GBEMU_37: number = 37;
const GBEMU_38: number = 38;
const GBEMU_39: number = 39;
const GBEMU_40: number = 40;
const GBEMU_88: number = 88;
const GBEMU_90: number = 90;
const GBEMU_41: number = 41;
const GBEMU_42: number = 42;
const GBEMU_43: number = 43;
const GBEMU_44: number = 44;
const GBEMU_45: number = 45;
const GBEMU_46: number = 46;
const GBEMU_47: number = 47;
const GBEMU_48: number = 48;
const GBEMU_49: number = 49;
const GBEMU_50: number = 50;
const GBEMU_51: number = 51;
const GBEMU_52: number = 52;
const GBEMU_53: number = 53;
const GBEMU_54: number = 54;
const GBEMU_55: number = 55;
const GBEMU_56: number = 56;
const GBEMU_57: number = 57;
const GBEMU_58: number = 58;
const GBEMU_59: number = 59;
const GBEMU_60: number = 60;
const GBEMU_61: number = 61;
const GBEMU_62: number = 62;
const GBEMU_63: number = 63;
const GBEMU_72: number = 72;
const GBEMU_80: number = 80;
const GBEMU_64: number = 64;
const GBEMU_96: number = 96;
const GBEMU_127: number = 127;
const GBEMU_128: number = 128;
const GBEMU_144: number = 144;
const GBEMU_160: number = 160;
const GBEMU_225: number = 225;
const GBEMU_252: number = 252;
const GBEMU_256: number = 256;
const GBEMU_512: number = 512;
const GBEMU_1000: number = 1000;
const GBEMU_1024: number = 1024;
const GBEMU_1985: number = 1985;
const GBEMU_4096: number = 4096;
const GBEMU_456: number = 456;
const GBEMU_298: number = 298;
const GBEMU_143: number = 143;
const GBEMU_154: number = 154;
const GBEMU_168: number = 168;
const GBEMU_74: number = 74;
const GBEMU_82: number = 82;
const GBEMU_222: number = 222;
const GBEMU_255: number = 255;
const GBEMU_239: number = 239;
const GBEMU_69120: number = 69120;
const GBEMU_248: number = 248;
const GBEMU_153: number = 153;
const GBEMU_312: number = 312;
const GBEMU_5016: number = 5016;
const GBEMU_100: number = 100;
const GBEMU_2047: number = 2047;
const GBEMU_8192: number = 8192;
const GBEMU_92160: number = 92160;
const GBEMU_250000: number = 250000;
const GBEMU_15000: number = 15000;
const GBEMU_44100: number = 44100;
const GBEMU_25000: number = 25000;
const GBEMU_23040: number = 23040;
const GBEMU_27044: number = 27044;
const GBEMU_48000: number = 48000;
const GBEMU_0xFF50: number = 0xff50;
const GBEMU_0x50: number = 0x50;
const GBEMU_0xFF6C: number = 0xff6c;
const GBEMU_0x6C: number = 0x6c;
const GBEMU_0x143: number = 0x143;
const GBEMU_0xFF74: number = 0xff74;
const GBEMU_0x74: number = 0x74;
const GBEMU_0xFF70: number = 0xff70;
const GBEMU_0x70: number = 0x70;
const GBEMU_0x10: number = 0x10;
const GBEMU_0xFF6B: number = 0xff6b;
const GBEMU_0x6B: number = 0x6b;
const GBEMU_0xFF6A: number = 0xff6a;
const GBEMU_0x6A: number = 0x6a;
const GBEMU_0xFF69: number = 0xff69;
const GBEMU_0x69: number = 0x69;
const GBEMU_0xFF68: number = 0xff68;
const GBEMU_0x68: number = 0x68;
const GBEMU_0xFF55: number = 0xff55;
const GBEMU_0x55: number = 0x55;
const GBEMU_0xFF4F: number = 0xff4f;
const GBEMU_0x4F: number = 0x4f;
const GBEMU_0x4D: number = 0x4d;
const GBEMU_0xFF4D: number = 0xff4d;
const GBEMU_0x49: number = 0x49;
const GBEMU_0xFF49: number = 0xff49;
const GBEMU_0x48: number = 0x48;
const GBEMU_0x1: number = 0x1;
const GBEMU_0xFF48: number = 0xff48;
const GBEMU_0xFF47: number = 0xff47;
const GBEMU_0x47: number = 0x47;
const GBEMU_0xFEA0: number = 0xfea0;
const GBEMU_0xFF46: number = 0xff46;
const GBEMU_0x46: number = 0x46;
const GBEMU_0xFE00: number = 0xfe00;
const GBEMU_0x41: number = 0x41;
const GBEMU_0xFF41: number = 0xff41;
const GBEMU_0x2: number = 0x2;
const GBEMU_0x08: number = 0x08;
const GBEMU_0x20: number = 0x20;
const GBEMU_0x40: number = 0x40;
const GBEMU_0xE0: number = 0xe0;
const GBEMU_0x7F: number = 0x7f;
const GBEMU_0x78: number = 0x78;
const GBEMU_0xFF40: number = 0xff40;
const GBEMU_0x01: number = 0x01;
const GBEMU_0x02: number = 0x02;
const GBEMU_0x04: number = 0x04;
const GBEMU_0x400: number = 0x400;
const GBEMU_0x80: number = 0x80;
const GBEMU_0xFF44: number = 0xff44;
const GBEMU_0xFF02: number = 0xff02;
const GBEMU_0xD000: number = 0xd000;
const GBEMU_0xE000: number = 0xe000;
const GBEMU_0x2000: number = 0x2000;
const GBEMU_0x07: number = 0x07;
const GBEMU_0xFF51: number = 0xff51;
const GBEMU_0xFF52: number = 0xff52;
const GBEMU_0x3F: number = 0x3f;
const GBEMU_0xFF: number = 0xff;
const GBEMU_0xFF54: number = 0xff54;
const GBEMU_0x54: number = 0x54;
const GBEMU_0xF0: number = 0xf0;
const GBEMU_0x53: number = 0x53;
const GBEMU_0xFF53: number = 0xff53;
const GBEMU_0x52: number = 0x52;
const GBEMU_0x51: number = 0x51;
const GBEMU_0x7f: number = 0x7f;
const GBEMU_0xff: number = 0xff;
const GBEMU_0xFFFFFF: number = 0xffffff;
const GBEMU_0x00: number = 0x00;
const GBEMU_0x13: number = 0x13;
const GBEMU_0xD8: number = 0xd8;
const GBEMU_0x014D: number = 0x014d;
const GBEMU_0xFFFE: number = 0xfffe;
const GBEMU_0x0100: number = 0x0100;
const GBEMU_0xA000: number = 0xa000;
const GBEMU_0xF000: number = 0xf000;
const GBEMU_0xEFFFDE: number = 0xefffde;
const GBEMU_0xADD794: number = 0xadd794;
const GBEMU_0x529273: number = 0x529273;
const GBEMU_0x183442: number = 0x183442;
const GBEMU_0x0F: number = 0x0f;
const GBEMU_0x7C: number = 0x7c;
const GBEMU_0xF8: number = 0xf8;
const GBEMU_0xBF: number = 0xbf;
const GBEMU_0xF3: number = 0xf3;
const GBEMU_0x77: number = 0x77;
const GBEMU_0xF1: number = 0xf1;
const GBEMU_0xFC: number = 0xfc;
const GBEMU_0x3E: number = 0x3e;
const GBEMU_0x9F: number = 0x9f;
const GBEMU_0x7E: number = 0x7e;
const GBEMU_0xFE: number = 0xfe;
const GBEMU_0x91: number = 0x91;
const GBEMU_0x8F: number = 0x8f;
const GBEMU_0xC0: number = 0xc0;
const GBEMU_0x0B: number = 0x0b;
const GBEMU_0xDC: number = 0xdc;
const GBEMU_0xDD: number = 0xdd;
const GBEMU_0x03: number = 0x03;
const GBEMU_0xCE: number = 0xce;
const GBEMU_0xED: number = 0xed;
const GBEMU_0xC1: number = 0xc1;
const GBEMU_0xE6: number = 0xe6;
const GBEMU_0x83: number = 0x83;
const GBEMU_0x6E: number = 0x6e;
const GBEMU_0x99: number = 0x99;
const GBEMU_0x3D: number = 0x3d;
const GBEMU_0x36: number = 0x36;
const GBEMU_0xD3: number = 0xd3;
const GBEMU_0x45: number = 0x45;
const GBEMU_0xBB: number = 0xbb;
const GBEMU_0xD0: number = 0xd0;
const GBEMU_0x98: number = 0x98;
const GBEMU_0x7A: number = 0x7a;
const GBEMU_0xEC: number = 0xec;
const GBEMU_0xEF: number = 0xef;
const GBEMU_0xD1: number = 0xd1;
const GBEMU_0x67: number = 0x67;
const GBEMU_0x66: number = 0x66;
const GBEMU_0x1F: number = 0x1f;
const GBEMU_0xCC: number = 0xcc;
const GBEMU_0x0D: number = 0x0d;
const GBEMU_0x63: number = 0x63;
const GBEMU_0x89: number = 0x89;
const GBEMU_0xB7: number = 0xb7;
const GBEMU_0xC2: number = 0x11;
const GBEMU_0x11: number = 0x11;
const GBEMU_0x71: number = 0x71;
const GBEMU_0xFA: number = 0xfa;
const GBEMU_0x88: number = 0x88;
const GBEMU_0xF4: number = 0xf4;
const GBEMU_0x9E: number = 0x9e;
const GBEMU_0xF9: number = 0xf9;
const GBEMU_0x0E: number = 0x0e;
const GBEMU_0x86: number = 0x86;
const GBEMU_0x5F: number = 0x5f;
const GBEMU_0x24: number = 0x24;
const GBEMU_0x5D: number = 0x5d;
const GBEMU_0x73: number = 0x73;
const GBEMU_0xFD: number = 0xfd;
const GBEMU_0x6D: number = 0x6d;
const GBEMU_0x12: number = 0x12;
const GBEMU_0x1D: number = 0x1d;
const GBEMU_0x2F: number = 0x2f;
const GBEMU_0x75: number = 0x75;
const GBEMU_0x05: number = 0x05;
const GBEMU_0x81: number = 0x81;
const GBEMU_0xB4: number = 0xb4;
const GBEMU_0x0C: number = 0x0c;
const GBEMU_0xB9: number = 0xb9;
const GBEMU_0xD9: number = 0xd9;
const GBEMU_0x33: number = 0x33;
const GBEMU_0x97: number = 0x97;
const GBEMU_0xE5: number = 0xe5;
const GBEMU_0x5E: number = 0x5e;
const GBEMU_0x06: number = 0x06;
const GBEMU_0xD5: number = 0xd5;
const GBEMU_0xAA: number = 0xaa;
const GBEMU_0x3A: number = 0x3a;
const GBEMU_0x418: number = 0x418;
const GBEMU_0x7FFF: number = 0x7fff;
const GBEMU_0x200: number = 0x200;
const GBEMU_0x800: number = 0x800;
const GBEMU_0x100: number = 0x100;
const GBEMU_0xFFFF: number = 0xffff;
const GBEMU_0xF: number = 0xf;
const GBEMU_0xFFF: number = 0xfff;
const GBEMU_0x60: number = 0x60;
const GBEMU_0x26: number = 0x26;
const GBEMU_0xFF26: number = 0xff26;
const GBEMU_0xFF27: number = 0xff27;
const GBEMU_0xFF28: number = 0xff28;
const GBEMU_0xFF29: number = 0xff29;
const GBEMU_0xFF2A: number = 0xff2a;
const GBEMU_0xFF2B: number = 0xff2b;
const GBEMU_0xFF2C: number = 0xff2c;
const GBEMU_0xFF2D: number = 0xff2d;
const GBEMU_0xFF2E: number = 0xff2e;
const GBEMU_0xFF2F: number = 0xff2f;
const GBEMU_0xFF30: number = 0xff30;
const GBEMU_0xFF31: number = 0xff31;
const GBEMU_0xFF32: number = 0xff32;
const GBEMU_0xFF33: number = 0xff33;
const GBEMU_0xFF34: number = 0xff34;
const GBEMU_0xFF35: number = 0xff35;
const GBEMU_0xFF36: number = 0xff36;
const GBEMU_0xFF37: number = 0xff37;
const GBEMU_0xFF38: number = 0xff38;
const GBEMU_0xFF39: number = 0xff39;
const GBEMU_0xFF3A: number = 0xff3a;
const GBEMU_0xFF3B: number = 0xff3b;
const GBEMU_0xFF3C: number = 0xff3c;
const GBEMU_0xFF3D: number = 0xff3d;
const GBEMU_0xFF3E: number = 0xff3e;
const GBEMU_0xFF3F: number = 0xff3f;
const GBEMU_0xFF00: number = 0xff00;
const GBEMU_0xFF42: number = 0xff42;
const GBEMU_0x42: number = 0x42;
const GBEMU_0xFF43: number = 0xff43;
const GBEMU_0x43: number = 0x43;
const GBEMU_0x44: number = 0x44;
const GBEMU_0xFF4A: number = 0xff4a;
const GBEMU_0x4A: number = 0x4a;
const GBEMU_0xFF56: number = 0xff56;
const GBEMU_0x3C: number = 0x3c;
const GBEMU_0x56: number = 0x56;
const GBEMU_0x6c: number = 0x6c;
const GBEMU_0xFF75: number = 0xff75;
const GBEMU_0xFF76: number = 0xff76;
const GBEMU_0xFF77: number = 0xff77;
const GBEMU_0xA060: number = 0xa060;
const GBEMU_0xA070: number = 0xa070;
const GBEMU_0xA080: number = 0xa080;
const GBEMU_0xA050: number = 0xa050;
const GBEMU_0xA040: number = 0xa040;
const GBEMU_0xA030: number = 0xa030;
const GBEMU_0xA020: number = 0xa020;
const GBEMU_0x09: number = 0x09;
const GBEMU_0x0A: number = 0x0a;
const GBEMU_0x0000: number = 0x0000;
const GBEMU_0x8000: number = 0x8000;
const GBEMU_0x4000: number = 0x4000;
const GBEMU_0x6000: number = 0x6000;
const GBEMU_0x1000: number = 0x1000;
const GBEMU_0x2100: number = 0x2100;
const GBEMU_0x2200: number = 0x2200;
const GBEMU_0x3000: number = 0x3000;
const GBEMU_0x9000: number = 0x9000;
const GBEMU_0x9800: number = 0x9800;
const GBEMU_0xC000: number = 0xc000;
const GBEMU_0x1FFF: number = 0x1fff;
const GBEMU_0xA200: number = 0xa200;
const GBEMU_0x7FF: number = 0x7ff;
const GBEMU_0x1800: number = 0x1800;
const GBEMU_0x8001: number = 0x8001;
const GBEMU_0x8002: number = 0x8002;
const GBEMU_0x8003: number = 0x8003;
const GBEMU_0x8004: number = 0x8004;
const GBEMU_0x8005: number = 0x8005;
const GBEMU_0x8006: number = 0x8006;
const GBEMU_0x8007: number = 0x8007;
const GBEMU_0x8008: number = 0x8008;
const GBEMU_0x8009: number = 0x8009;
const GBEMU_0x800A: number = 0x800a;
const GBEMU_0x800B: number = 0x800b;
const GBEMU_0x800C: number = 0x800c;
const GBEMU_0x800D: number = 0x800d;
const GBEMU_0x800E: number = 0x800e;
const GBEMU_0x800F: number = 0x800f;
const GBEMU_0x7F0: number = 0x7f0;
const GBEMU_0x1FF0: number = 0x1ff0;
const GBEMU_0xFFF0: number = 0xfff0;
const GBEMU_0x3: number = 0x3;
const GBEMU_0x4: number = 0x4;
const GBEMU_0x5: number = 0x5;
const GBEMU_0x6: number = 0x6;
const GBEMU_0x7: number = 0x7;
const GBEMU_0x8: number = 0x8;
const GBEMU_0x9: number = 0x9;
const GBEMU_0xA: number = 0xa;
const GBEMU_0xB: number = 0xb;
const GBEMU_0xC: number = 0xc;
const GBEMU_0xD: number = 0xd;
const GBEMU_0xE: number = 0xe;
const GBEMU_0x30: number = 0x30;
const GBEMU_0xFF01: number = 0xff01;
const GBEMU_0xFF04: number = 0xff04;
const GBEMU_0xFF05: number = 0xff05;
const GBEMU_0xFF06: number = 0xff06;
const GBEMU_0xFF07: number = 0xff07;
const GBEMU_0xFF0F: number = 0xff0f;
const GBEMU_0xFF10: number = 0xff10;
const GBEMU_0xFF11: number = 0xff11;
const GBEMU_0xFF12: number = 0xff12;
const GBEMU_0xFF13: number = 0xff13;
const GBEMU_0xFF14: number = 0xff14;
const GBEMU_0x700: number = 0x700;
const GBEMU_0x0: number = 0x0;
const GBEMU_0x14: number = 0x14;
const GBEMU_0xFF16: number = 0xff16;
const GBEMU_0x16: number = 0x16;
const GBEMU_0xFF17: number = 0xff17;
const GBEMU_0x17: number = 0x17;
const GBEMU_0xFF18: number = 0xff18;
const GBEMU_0x18: number = 0x18;
const GBEMU_0xFF19: number = 0xff19;
const GBEMU_0x19: number = 0x19;
const GBEMU_0xFF1A: number = 0xff1a;
const GBEMU_0x1A: number = 0x1a;
const GBEMU_0xFF1B: number = 0xff1b;
const GBEMU_0x1B: number = 0x1b;
const GBEMU_0xFF1C: number = 0xff1c;
const GBEMU_0x1C: number = 0x1c;
const GBEMU_0xFF1D: number = 0xff1d;
const GBEMU_0xFF1E: number = 0xff1e;
const GBEMU_0x1E: number = 0x1e;
const GBEMU_0x21: number = 0x21;
const GBEMU_0x22: number = 0x22;
const GBEMU_0x23: number = 0x23;
const GBEMU_0x25: number = 0x25;
const GBEMU_0x27: number = 0x27;
const GBEMU_0x28: number = 0x28;
const GBEMU_0x29: number = 0x29;
const GBEMU_0xFF20: number = 0xff20;
const GBEMU_0xFF21: number = 0xff21;
const GBEMU_0xFF22: number = 0xff22;
const GBEMU_0xFF23: number = 0xff23;
const GBEMU_0xFF24: number = 0xff24;
const GBEMU_0xFF25: number = 0xff25;
const GBEMU_0x2A: number = 0x2a;
const GBEMU_0x2B: number = 0x2b;
const GBEMU_0x2C: number = 0x2c;
const GBEMU_0x2E: number = 0x2e;
const GBEMU_0x2D: number = 0x2d;
const GBEMU_0x31: number = 0x31;
const GBEMU_0x32: number = 0x32;
const GBEMU_0x34: number = 0x34;
const GBEMU_0x35: number = 0x35;
const GBEMU_0x37: number = 0x37;
const GBEMU_0x38: number = 0x38;
const GBEMU_0x39: number = 0x39;
const GBEMU_0x3B: number = 0x3b;
const GBEMU_0xFF45: number = 0xff45;
const GBEMU_0xFF4B: number = 0xff4b;
const GBEMU_0x4B: number = 0x4b;
const GBEMU_0xFF72: number = 0xff72;
const GBEMU_0xFF73: number = 0xff73;
const GBEMU_0x72: number = 0x72;
const GBEMU_0x76: number = 0x76;
const GBEMU_0x0080: number = 0x0080;
const GBEMU_0x0001: number = 0x0001;
const GBEMU_0xFF80: number = 0xff80;
const GBEMU_0xF00: number = 0xf00;
const GBEMU_0x0200: number = 0x0200;
const GBEMU_0x0002: number = 0x0002;
const GBEMU_0x0400: number = 0x0400;
const GBEMU_0x0004: number = 0x0004;
const GBEMU_0x0800: number = 0x0800;
const GBEMU_0x0008: number = 0x0008;
const GBEMU_0x0010: number = 0x0010;
const GBEMU_0x0020: number = 0x0020;
const GBEMU_0x0040: number = 0x0040;
const GBEMU_0xFEFF: number = 0xfeff;
const GBEMU_0xFDFF: number = 0xfdff;
const GBEMU_0xFFFD: number = 0xfffd;
const GBEMU_0xFF1F: number = 0xff1f;
const GBEMU_0x600: number = 0x600;
const GBEMU_0x1FFE: number = 0x1ffe;
const GBEMU_0x9FFE: number = 0x9ffe;
const GBEMU_0xA00: number = 0xa00;
const GBEMU_0xC00: number = 0xc00;
const GBEMU_0xE00: number = 0xe00;
const GBEMU_0x1000000: number = 0x1000000;
const GBEMU_0x2000000: number = 0x2000000;
const GBEMU_0x1f: number = 0x1f;
const GBEMU_0xf80: number = 0xf80;
const GBEMU_0xF8F8F8: number = 0xf8f8f8;
const GBEMU_0x7B: number = 0x7b;
const GBEMU_0xf: number = 0xf;
const GBEMU_0xF7: number = 0xf7;
const GBEMU_0xFB: number = 0xfb;
const GBEMU_0xF0F0: number = 0xf0f0;
const GBEMU_0x1FF: number = 0x1ff;
const GBEMU_0x10000: number = 0x10000;
const GBEMU_0x780: number = 0x780;
const GBEMU_0x680: number = 0x680;
const GBEMU_0x500: number = 0x500;
const GBEMU_0x580: number = 0x580;
const GBEMU_0x480: number = 0x480;
const GBEMU_0x380: number = 0x380;
const GBEMU_0x300: number = 0x300;
const GBEMU_0x280: number = 0x280;
const GBEMU_0x180: number = 0x180;
const GBEMU_0x080: number = 0x080;
const GBEMU_0x78000: number = 0x78000;
const GBEMU_0x70000: number = 0x70000;
const GBEMU_0x68000: number = 0x68000;
const GBEMU_0x60000: number = 0x60000;
const GBEMU_0x58000: number = 0x58000;
const GBEMU_0x50000: number = 0x50000;
const GBEMU_0x48000: number = 0x48000;
const GBEMU_0x40000: number = 0x40000;
const GBEMU_0x38000: number = 0x38000;
const GBEMU_0x30000: number = 0x30000;
const GBEMU_0x28000: number = 0x28000;
const GBEMU_0x20000: number = 0x20000;
const GBEMU_0x18000: number = 0x18000;
const GBEMU_0x08000: number = 0x08000;
const GBEMU_0x3FFF: number = 0x3fff;
const GBEMU_0x80000: number = 0x80000;
const GBEMU_0x400000: number = 0x400000;
const GBEMU_0x7000: number = 0x7000;
const GBEMU_0x7D: number = 0x7d;
const GBEMU_0x900: number = 0x900;
const GBEMU_0x144: number = 0x144;
const GBEMU_0x145: number = 0x145;
const GBEMU_0x14B: number = 0x14b;
const GBEMU_0x148: number = 0x148;
const GBEMU_0x149: number = 0x149;
const GBEMU_0x7ff: number = 0x7ff;
const GBEMU_0xfe: number = 0xfe;
const GBEMU_0x1fff: number = 0x1fff;
const GBEMU_0xC3: number = 0xc3;
const GBEMU_0xFFFFFFFF: number = 0xffffffff;
const GBEMU_0xFFFFFFFE: number = 0xfffffffe;
const GBEMU_0x9A: number = 0x9a;
const GBEMU_0xA0: number = 0xa0;
const GBEMU_0x80FF: number = 0x80ff;
const GBEMU_0xFBFF: number = 0xfbff;
const GBEMU_0xFFFB: number = 0xfffb;
const GBEMU_0xF7FF: number = 0xf7ff;
const GBEMU_0xFFF7: number = 0xfff7;
const GBEMU_0xEFFF: number = 0xefff;
const GBEMU_0xFFEF: number = 0xffef;
const GBEMU_0xDF: number = 0xdf;
const GBEMU_0xDFFF: number = 0xdfff;
const GBEMU_0xFFDF: number = 0xffdf;
const GBEMU_0xBFFF: number = 0xbfff;
const GBEMU_0xFFBF: number = 0xffbf;
const GBEMU_0xFF7F: number = 0xff7f;
const GBEMU_0x101: number = 0x101;
const GBEMU_0x134: number = 0x134;
const GBEMU_0x13F: number = 0x13f;
const GBEMU_0x147: number = 0x147;

// ------ gbemu-part1 ------
let decodedGameboyRom: string = '';

/*
 * @State
 * @Tags Jetstream2
 */
class Benchmark {
  /*
   * @Setup
   */
  setupGameboy(): void {
    initializeWebKitAudio();
    decodedGameboyRom = base64Decode(gameboyRom);
  }
  /*
   * @Benchmark
   */
  runGameboy(): void {
    //debugLog('This is runGameboy')
    start(new GameBoyCanvas(), decodedGameboyRom);

    gameboy!.instructions = 0;
    gameboy!.totalInstructions = GBEMU_250000;

    while (gameboy!.instructions <= gameboy!.totalInstructions) {
      //debugLog(`This is runGameboy instructions: ${gameboy!.instructions}`);
      gameboy!.run();
      gameBoyAudioNode!.run();
    }

    resetGlobalVariables();
  }
  /*
   * @Teardown
   */
  tearDownGameboy(): void {
    decodedGameboyRom = '';
    expectedGameboyStateStr = '';
  }
}

let expectedGameboyStateStr: string = `{'registerA':160,'registerB':255,'registerC':255,'registerE':11,'registersHL':51600,'programCounter':24309,'stackPointer':49706,'sumrom':10171578,'sumMemory':3435856,'summbcRam':234598,'sumVRam':0}`;

// Start of browser emulation.

class GameBoyWindowClass {
  opera: boolean = false;
  mozRequestAnimationFrame: boolean = false;
}

let gameBoyWindow = new GameBoyWindowClass();

class GameBoyContext {
  createImageData(w: number, h: number): GameBoyContextImageDataResult {
    let result = new GameBoyContextImageDataResult();
    result.data = new Uint8Array(w * h * GBEMU_4);
    return result;
  }
  putImageData(buffer: GameBoyContextImageDataResult, x: number, y: number): void {
    let sum = 0;
    for (let i = 0; i < buffer.data.length; i++) {
      sum += i * buffer.data[i];
      sum = sum % GBEMU_1000;
    }
  }
  drawImage(canvas?: GameBoyCanvas, x?: number, y?: number, screenWidth?: number, screenHeight?: number): void {}
}

class GameBoyContextImageDataResult {
  data: Uint8Array = new Uint8Array();
}

class GameBoyCanvas {
  width: number = GBEMU_160;
  height: number = GBEMU_144;
  clientWidth: number = 0;
  clientHeight: number = 0;
  style: GameBoyCanvasStyle = new GameBoyCanvasStyle();
  getContext(type: string): GameBoyContext {
    return new GameBoyContext();
  }
}

class GameBoyCanvasStyle {
  visibility: string = 'visibile';
}

function cout(message: string, colorIndex: number): void {}

class GameBoyAudioNodeConstrc {
  bufferSize: number = 0;
  outputBuffer: GameBoyAudioNodeBuffer | null = null;
  onaudioprocess: ((event: GameBoyAudioNodeEvent) => void) | null = null;
  connect(destination: GameBoyAudioContextDestination): void {}
  run(): void {
    let event: GameBoyAudioNodeEvent = new GameBoyAudioNodeEvent();
    event.outputBuffer = this.outputBuffer as GameBoyAudioNodeBuffer;
    this.onaudioprocess!(event);
  }
}

let gameBoyAudioNode = new GameBoyAudioNodeConstrc();

class GameBoyAudioNodeEvent {
  outputBuffer: GameBoyAudioNodeBuffer | null = null;
}

class GameBoyAudioNodeBuffer {
  channelData: Float32Array[] = [];
  getChannelData(i: number): Float32Array {
    return this.channelData[i];
  }
}

class GameBoyAudioContext {
  sampleRate: number = GBEMU_48000;
  destination: GameBoyAudioContextDestination | null = new GameBoyAudioContextDestination();
  createBufferSource(): GameBoyAudioContextBufferSource {
    return new GameBoyAudioContextBufferSource();
  }
  createBuffer(channels: number, len: number, sampleRate: number): GameBoyAudioContextBuffer {
    return new GameBoyAudioContextBuffer(1, 1, 1, GBEMU_DURATION, GBEMU_48000);
  }
  createJavaScriptNode(bufferSize: number, inputChannels: number, outputChannels: number): GameBoyAudioNodeConstrc {
    gameBoyAudioNode.bufferSize = bufferSize;
    gameBoyAudioNode.outputBuffer = new GameBoyAudioNodeBuffer();
    for (let i = 0; i < outputChannels; i++) {
      gameBoyAudioNode.outputBuffer.channelData[i] = new Float32Array(bufferSize);
    }
    return gameBoyAudioNode;
  }
}

class GameBoyAudioContextBufferSource {
  loop: boolean = false;
  buffer: GameBoyAudioContextBuffer | null = null;
  noteOn(index: number): void {}
  connect(audioNode: GameBoyAudioNodeConstrc): void {}
}

class GameBoyAudioContextDestination {}

class GameBoyAudioContextBuffer {
  gain: number;
  numberOfChannels: number;
  length: number;
  duration: number;
  sampleRate: number;
  constructor(gain: number, numberOfChannels: number, length: number, duration: number, sampleRate: number) {
    this.gain = gain;
    this.numberOfChannels = numberOfChannels;
    this.length = length;
    this.duration = duration;
    this.sampleRate = sampleRate;
  }
}

let mockDateTimeCounter: number = 0;

class NewDate {
  getTime(): number {
    mockDateTimeCounter += GBEMU_16;
    return mockDateTimeCounter;
  }
}

// End of browser emulation.

// Start of helper functions.

function checkFinalState(): void {
  let stateStr: string = `{'registerA':${gameboy!.registerA},'registerB':${gameboy!.registerB},'registerC':${gameboy!.registerC},'registerE':${
    gameboy!.registerE
  },'registersHL':${gameboy!.registersHL},'programCounter':${gameboy!.programCounter},'stackPointer':${gameboy!.stackPointer},'sumrom':${setStateSum(
    gameboy!.fromTypedArray(gameboy!.rom)
  )},'sumMemory':${setStateSum(gameboy!.fromTypedArray(gameboy!.memory))},'summbcRam':${setStateSum(
    gameboy!.fromTypedArray(gameboy!.mbcRam)
  )},'sumVRam':${setStateSum(gameboy!.fromTypedArray(gameboy!.vram as TNextArray))}}`;
  if (expectedGameboyStateStr.length > 0) {
    if (stateStr !== expectedGameboyStateStr) {
    }
  } else {
  }
}

function setStateSum(a: TNextArray): number {
  let result = 0;
  for (let i = 0; i < a.length; i++) {
    result += a[i];
  }
  return result;
}

function resetGlobalVariables(): void {
  //debugLog('This is resetGlobalVariables');
  //Audio API Event Handler:
  audioContextHandle = null;
  audioNode = null;
  audioSource = null;
  launchedContext = false;
  audioContextSampleBuffer = new Float32Array();
  resampled = new Float32Array();
  webAudioMinBufferSize = GBEMU_15000;
  webAudioMaxBufferSize = GBEMU_25000;
  webAudioActualSampleRate = GBEMU_44100;
  xAudioJSSampleRate = 0;
  webAudioMono = false;
  xAudioJSVolume = 1;
  resampleControl = null;
  audioBufferSize = 0;
  resampleBufferStart = 0;
  resampleBufferEnd = 0;
  resampleBufferSize = GBEMU_2;
  gameboy = null; //GameBoyCore object.
}

// End of helper functions.

// Original code from Grant Galitz follows.
// Modifications by Google are marked in comments.

// Start of js/other/base64.js file.

let toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let base64Pad: string = '=';

/* Convert Base64 data to a string */
let toBinaryTable: Array<number> = [
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, GBEMU_62, -1, -1, -1, GBEMU_63, GBEMU_52, GBEMU_53, GBEMU_54, GBEMU_55, GBEMU_56, GBEMU_57, GBEMU_58, GBEMU_59, GBEMU_60, GBEMU_61, -1, -1, -1, 0, -1, -1, -1, 0, 1, GBEMU_2, GBEMU_3, GBEMU_4, GBEMU_5, GBEMU_6, GBEMU_7, GBEMU_8, GBEMU_9, GBEMU_10, GBEMU_11, GBEMU_12, GBEMU_13, GBEMU_14, GBEMU_15, GBEMU_16, GBEMU_17, GBEMU_18, GBEMU_19, GBEMU_20, GBEMU_21, GBEMU_22, GBEMU_23, GBEMU_24, GBEMU_25, -1, -1, -1, -1, -1, -1, GBEMU_26, GBEMU_27, GBEMU_28, GBEMU_29, GBEMU_30, GBEMU_31, GBEMU_32, GBEMU_33, GBEMU_34, GBEMU_35, GBEMU_36, GBEMU_37, GBEMU_38, GBEMU_39, GBEMU_40, GBEMU_41, GBEMU_42, GBEMU_43, GBEMU_44, GBEMU_45, GBEMU_46, GBEMU_47, GBEMU_48, GBEMU_49, GBEMU_50, GBEMU_51, -1, -1, -1, -1, -1
];

function base64Decode(data: string): string {
  let result: string = '';
  let leftbits: number = 0; // number of bits decoded, but yet to be appended
  let leftdata: number = 0; // bits decoded, but yet to be appended

  for (let i = 0; i < data.length; i++) {
    let c = toBinaryTable[data.charCodeAt(i) & GBEMU_0x7f];
    let padding = data.charCodeAt(i) === base64Pad.charCodeAt(0);
    // Skip illegal characters and whitespace
    if (c === -1) continue;

    // Collect data into leftdata, update bitcount
    leftdata = (leftdata << GBEMU_6) | c;
    leftbits += GBEMU_6;

    // If we have GBEMU_8 or more bits, append GBEMU_8 bits to the result
    if (leftbits >= GBEMU_8) {
      leftbits -= GBEMU_8;
      // Append if not padding.
      if (!padding) {
        result += String.fromCharCode((leftdata >> leftbits) & GBEMU_0xff);
      }
      leftdata &= (1 << leftbits) - 1;
    }
  }
  return result;
}
// End of js/other/base64.js file.

// Start of js/other/resampler.js file.

//JavaScript Audio Resampler (c) 2011 - Grant Galitz
class Resampler {
  fromSampleRate: number = 0;
  toSampleRate: number = 0;
  channels: number = 0;
  outputBufferSize: number = 0;
  noReturn: boolean = false;
  resampler: (buffer: Float32Array) => Float32Array | number | undefined = () => new Float32Array();
  ratioWeight: number = 0;
  tailExists: boolean = false;
  lastWeight: number = 0;
  lastOutput: Float32Array = new Float32Array();
  outputBuffer: Float32Array = new Float32Array();
  constructor(fromSampleRate: number, toSampleRate: number, channels: number = 0, outputBufferSize: number, noReturn: boolean) {
    this.fromSampleRate = fromSampleRate;
    this.toSampleRate = toSampleRate;
    this.channels = channels | 0;
    this.outputBufferSize = outputBufferSize;
    this.noReturn = noReturn;
    this.initialize();
  }
  initialize(): void {
    //Perform some checks:
    if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) {
      if (this.fromSampleRate === this.toSampleRate) {
        //Setup a resampler bypass:
        this.resampler = this.bypassResampler; //Resampler just returns what was passed through.
        this.ratioWeight = 1;
      } else {
        //Setup the interpolation resampler:
        this.resampler = this.interpolate; //Resampler is a custom quality interpolation algorithm.
        this.ratioWeight = this.fromSampleRate / this.toSampleRate;
        this.tailExists = false;
        this.lastWeight = 0;
        this.initializeBuffers();
      }
    } else {
    }
  }
  interpolate(buffer: Float32Array): Float32Array | number {
    let bufferLength: number = Math.min(buffer.length, this.outputBufferSize);
    if (bufferLength % GBEMU_2 === 0) {
      if (bufferLength > 0) {
        let ratioWeight: number = this.ratioWeight;
        let weight: number = 0;
        let output0: number = 0;
        let output1: number = 0;
        let actualPosition: number = 0;
        let amountToNext: number = 0;
        let alreadyProcessedTail: boolean = !this.tailExists;
        this.tailExists = false;
        let outputBuffer: Float32Array = this.outputBuffer;
        let outputOffset: number = 0;
        let currentPosition: number = 0;
        do {
          if (alreadyProcessedTail) {
            weight = ratioWeight;
            output0 = 0;
            output1 = 0;
          } else {
            weight = this.lastWeight;
            output0 = this.lastOutput[0];
            output1 = this.lastOutput[1];
            alreadyProcessedTail = true;
          }
          while (weight > 0 && actualPosition < bufferLength) {
            amountToNext = 1 + actualPosition - currentPosition;
            if (weight >= amountToNext) {
              output0 += buffer[actualPosition++] * amountToNext;
              output1 += buffer[actualPosition++] * amountToNext;
              currentPosition = actualPosition;
              weight -= amountToNext;
            } else {
              output0 += buffer[actualPosition] * weight;
              output1 += buffer[actualPosition + 1] * weight;
              currentPosition += weight;
              weight = 0;
              break;
            }
          }
          if (weight === 0) {
            outputBuffer[outputOffset++] = output0 / ratioWeight;
            outputBuffer[outputOffset++] = output1 / ratioWeight;
          } else {
            this.lastWeight = weight;
            this.lastOutput[0] = output0;
            this.lastOutput[1] = output1;
            this.tailExists = true;
            break;
          }
        } while (actualPosition < bufferLength);
        return this.bufferSlice(outputOffset);
      } else {
        return this.noReturn ? 0 : new Float32Array();
      }
    } else {
    }
    return new Float32Array();
  }

  bypassResampler(buffer: Float32Array): Float32Array | number {
    if (this.noReturn) {
      //Set the buffer passed as our own, as we don't need to resample it:
      this.outputBuffer = buffer;
      return buffer.length;
    } else {
      //Just return the buffer passsed:
      return buffer;
    }
  }
  bufferSlice(sliceAmount: number): Float32Array | number {
    if (this.noReturn) {
      //If we're going to access the properties directly from this object:
      return sliceAmount;
    } else {
      //Typed array and normal array buffer section referencing:
      return this.outputBuffer.subarray(0, sliceAmount);
    }
  }
  initializeBuffers(): void {
    //Initialize the internal buffer:
    this.outputBuffer = new Float32Array(this.outputBufferSize);
    this.lastOutput = new Float32Array(this.channels);
  }
}

// End of js/other/resampler.js file.

// Start of js/other/XAudioServer.js file.

/*Initialize here first:
  Example:
    Stereo audio with a sample rate of 70 khz, a minimum buffer of 15000 samples total, a maximum buffer of 25000 samples total and a starting volume level of 1.
      var parentObj = this;
      this.audioHandle = new XAudioServer(GBEMU_2, GBEMU_70000, GBEMU_15000, GBEMU_25000, function (sampleCount) {
        return parentObj.audioUnderRun(sampleCount);
      }, 1);

  The callback is passed the number of samples requested, while it can return any number of samples it wants back.
*/
class XAudioServer {
  audioChannels: number = 0;
  channels: number = 0;
  sampleRate: number = 0;
  minBufferSize: number = 0;
  maxBufferSize: number = 0;
  volume: number = 0;
  audioType: number = -1;
  mozAudioTail: number[] = [];
  audioHandleMoz: Object | null = null;
  audioHandleFlash: XAudioServer | null = null;
  flashInitialized: boolean = false;
  mozAudioFound: boolean = false;
  underRunCallback: (samplesRequested: number) => void;
  constructor(
    channels: number = 0,
    sampleRate: number = 0,
    minBufferSize: number = 0,
    maxBufferSize: number = 0,
    underRunCallback: ((samplesRequested: number) => void) | null,
    volume: number = 0
  ) {
    this.channels = channels;
    this.sampleRate = sampleRate;
    this.minBufferSize = minBufferSize;
    this.maxBufferSize = maxBufferSize;
    this.volume = volume;
    this.audioChannels = channels === GBEMU_2 ? GBEMU_2 : 1;
    webAudioMono = this.audioChannels === 1;
    xAudioJSSampleRate = sampleRate > 0 && sampleRate <= GBEMU_0xFFFFFF ? sampleRate : GBEMU_44100;
    webAudioMinBufferSize =
      minBufferSize >= samplesPerCallback << 1 && minBufferSize < maxBufferSize ?
        minBufferSize & (webAudioMono ? GBEMU_0xFFFFFFFF : GBEMU_0xFFFFFFFE) :
        samplesPerCallback << 1;
    webAudioMaxBufferSize =
      Math.floor(maxBufferSize) > webAudioMinBufferSize + this.audioChannels ?
        maxBufferSize & (webAudioMono ? GBEMU_0xFFFFFFFF : GBEMU_0xFFFFFFFE) :
        minBufferSize << 1;
    this.underRunCallback = typeof underRunCallback === 'function' ? underRunCallback : (): void => {};
    xAudioJSVolume = volume >= 0 && volume <= 1 ? volume : 1;
    this.initializeAudio();
  }
  callbackBasedWriteAudioNoCallback(buffer: Float32Array): void {
    //Callback-centered audio APIs:
    let length: number = buffer.length;
    let bufferCounter: number = 0;
    while (bufferCounter < length && audioBufferSize < webAudioMaxBufferSize) {
      audioContextSampleBuffer[audioBufferSize++] = buffer[bufferCounter++];
    }
  }
  /*Pass your samples into here if you don't want automatic callback calling:
  Pack your samples as a one-dimenional array
  With the channel samplea packed uniformly.
  examples:
      mono - [left, left, left, left]
      stereo - [left, right, left, right, left, right, left, right]
  Useful in preventing infinite recursion issues with calling writeAudio inside your callback.
  */
  writeAudioNoCallback(buffer: Float32Array): void {
    if (this.audioType === 0) {
    } else if (this.audioType === 1) {
      this.callbackBasedWriteAudioNoCallback(buffer);
    } else if (this.audioType === GBEMU_2) {
      if (this.checkFlashInit() || launchedContext) {
        this.callbackBasedWriteAudioNoCallback(buffer);
      } else if (this.mozAudioFound) {
      }
    }
  }
  //Developer can use this to see how many samples to write (example: minimum buffer allotment minus remaining samples left returned from this function to make sure maximum buffering is done...)
  //If -1 is returned, then that means metric could not be done.
  remainingBuffer(): number {
    if (this.audioType === 0) {
      //mozAudio:
    } else if (this.audioType === 1) {
      //WebKit Audio:
      return (((resampledSamplesLeft() * resampleControl!.ratioWeight) >> (this.audioChannels - 1)) << (this.audioChannels - 1)) + audioBufferSize;
    } else if (this.audioType === GBEMU_2) {
      if (this.checkFlashInit() || launchedContext) {
        //Webkit Audio / Flash Plugin Audio:
        return (((resampledSamplesLeft() * resampleControl!.ratioWeight) >> (this.audioChannels - 1)) << (this.audioChannels - 1)) + audioBufferSize;
      } else if (this.mozAudioFound) {
        //mozAudio:
      }
    }
    //Default return:
    return 0;
  }
  //DO NOT CALL THIS, the lib calls this internally!
  initializeAudio(): void {
    if (launchedContext) {
      this.initializeWebAudio();
    } else {
      this.initializeFlashAudio();
    }
  }
  initializeWebAudio(): void {
    resetCallbackAPIAudioBuffer(webAudioActualSampleRate, samplesPerCallback);
    this.audioType = 1;
  }
  changeVolume(newVolume: number): void {
    if (newVolume >= 0 && newVolume <= 1) {
      xAudioJSVolume = newVolume;
      if (this.checkFlashInit()) {
      }
    }
  }
  initializeFlashAudio(): void {}
  //Checks to see if the NPAPI Adobe Flash bridge is ready yet:
  checkFlashInit(): boolean {
    return this.flashInitialized;
  }
}

class Audio {}

/////////END LIB
function getFloat32(size: number): Float32Array {
  return new Float32Array(size);
}
function getFloat32Flat(size: number): Float32Array {
  return new Float32Array(size);
}
//Flash NPAPI Event Handler:
let samplesPerCallback: number = 2048; //Has to be between 2048 and 4096 (If over, then samples are ignored, if under then silence is added).
let outputConvert: object | null = null;
function generateFlashStereoString(): string {
  //Convert the arrays to one long string for speed.
  let copyBinaryStringLeft: string = '';
  let copyBinaryStringRight: string = '';
  let index: number = 0;
  while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
    //Sanitize the buffer:
    copyBinaryStringLeft += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
    copyBinaryStringRight += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
    if (resampleBufferStart === resampleBufferSize) {
      resampleBufferStart = 0;
    }
    index += 1;
  }
  return copyBinaryStringLeft + copyBinaryStringRight;
}
function generateFlashMonoString(): string {
  //Convert the array to one long string for speed.
  let copyBinaryString: string = '';
  let index: number = 0;
  while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
    //Sanitize the buffer:
    copyBinaryString += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
    if (resampleBufferStart === resampleBufferSize) {
      resampleBufferStart = 0;
    }
    index += 1;
  }
  return copyBinaryString;
}

//Audio API Event Handler:
let audioContextHandle: GameBoyAudioContext | null = null;
let audioNode: GameBoyAudioNodeConstrc | null = null;
let audioSource: GameBoyAudioContextBufferSource | null = null;
let launchedContext: boolean = false;
let audioContextSampleBuffer: Float32Array = new Float32Array();
let resampled: Float32Array = new Float32Array();
let webAudioMinBufferSize = GBEMU_15000;
let webAudioMaxBufferSize: number = GBEMU_250000;
let webAudioActualSampleRate: number = GBEMU_44100;
let xAudioJSSampleRate: number = 0;
let webAudioMono: boolean = false;
let xAudioJSVolume: number = 1;
let resampleControl: Resampler | null = null;
let audioBufferSize: number = 0;
let resampleBufferStart: number = 0;
let resampleBufferEnd: number = 0;
let resampleBufferSize: number = GBEMU_2;

function audioOutputEvent(event: GameBoyAudioNodeEvent): void {
  //Web Audio API callback...
  let index: number = 0;
  let buffer1: Float32Array = event.outputBuffer!.getChannelData(0);
  let buffer2: Float32Array = event.outputBuffer!.getChannelData(1);
  resampleRefill();
  if (!webAudioMono) {
    //STEREO:
    while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
      buffer1[index] = resampled[resampleBufferStart++] * xAudioJSVolume;
      buffer2[index++] = resampled[resampleBufferStart++] * xAudioJSVolume;
      if (resampleBufferStart === resampleBufferSize) {
        resampleBufferStart = 0;
      }
    }
  } else {
    //MONO:
    while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
      buffer1[index] = resampled[resampleBufferStart++] * xAudioJSVolume;
      buffer2[index] = buffer1[index];
      index += 1;
      if (resampleBufferStart === resampleBufferSize) {
        resampleBufferStart = 0;
      }
    }
  }
  //Pad with silence if we're underrunning:
  while (index < samplesPerCallback) {
    buffer1[index] = 0;
    buffer2[index] = 0;
    index += 1;
  }
}

function resampleRefill(): void {
  if (audioBufferSize > 0) {
    //Resample a chunk of audio:
    let resampleLength: number = resampleControl!.resampler(getBufferSamples()) as number;
    let resampledResult: Float32Array = resampleControl!.outputBuffer;
    for (let index2: number = 0; index2 < resampleLength; ++index2) {
      resampled[resampleBufferEnd++] = resampledResult[index2];
      if (resampleBufferEnd === resampleBufferSize) {
        resampleBufferEnd = 0;
      }
      if (resampleBufferStart === resampleBufferEnd) {
        resampleBufferStart += 1;
        if (resampleBufferStart === resampleBufferSize) {
          resampleBufferStart = 0;
        }
      }
    }
    audioBufferSize = 0;
  }
}

function resampledSamplesLeft(): number {
  return (resampleBufferStart <= resampleBufferEnd ? 0 : resampleBufferSize) + resampleBufferEnd - resampleBufferStart;
}

function getBufferSamples(): Float32Array {
  // Typed array and normal array buffer section referencing:
  return audioContextSampleBuffer.subarray(0, audioBufferSize);
}

//Initialize WebKit Audio /Flash Audio Buffer:
function resetCallbackAPIAudioBuffer(APISampleRate: number, bufferAlloc: number): void {
  audioContextSampleBuffer = getFloat32(webAudioMaxBufferSize);
  audioBufferSize = webAudioMaxBufferSize;
  resampleBufferStart = 0;
  resampleBufferEnd = 0;
  resampleBufferSize = Math.max(webAudioMaxBufferSize * Math.ceil(xAudioJSSampleRate / APISampleRate), samplesPerCallback) << 1;
  if (webAudioMono) {
    //MONO Handling:
    resampled = getFloat32Flat(resampleBufferSize);
    resampleControl = new Resampler(xAudioJSSampleRate, APISampleRate, 1, resampleBufferSize, true);
    outputConvert = generateFlashMonoString;
  } else {
    //STEREO Handling:
    resampleBufferSize <<= 1;
    resampled = getFloat32Flat(resampleBufferSize);
    resampleControl = new Resampler(xAudioJSSampleRate, APISampleRate, GBEMU_2, resampleBufferSize, true);
    outputConvert = generateFlashStereoString;
  }
}

//Initialize WebKit Audio:
function initializeWebKitAudio(): void {
  //debugLog('This is initializeWebKitAudio')
  if (!launchedContext) {
    // The following line was modified for benchmarking:
    audioContextHandle = new GameBoyAudioContext(); //Create a system audio context.
    audioSource = audioContextHandle.createBufferSource(); //We need to create a false input to get the chain started.
    audioSource.loop = false; //Keep this alive forever (Event handler will know when to ouput.)
    xAudioJSSampleRate = audioContextHandle.sampleRate;
    webAudioActualSampleRate = audioContextHandle.sampleRate;
    audioSource.buffer = audioContextHandle.createBuffer(1, 1, webAudioActualSampleRate); //Create a zero'd input buffer for the input to be valid.
    audioNode = audioContextHandle.createJavaScriptNode(samplesPerCallback, 1, GBEMU_2); //Create GBEMU_2 outputs and ignore the input buffer (Just copy buffer 1 over if mono)
    audioNode.onaudioprocess = audioOutputEvent; //Connect the audio processing event to a handling function so we can manipulate output
    audioSource.connect(audioNode); //Send and chain the input to the audio manipulation.
    audioNode.connect(audioContextHandle.destination as GameBoyAudioContextDestination); //Send and chain the output of the audio manipulation to the system audio output.
    audioSource.noteOn(0); //Start the loop!
    launchedContext = true;
  }
}
// End of js/other/XAudioServer.js file.

// Start of js/other/resize.js file.

//JavaScript Image Resizer (c) 2012 - Grant Galitz
class Resize {
  widthOriginal: number = 0;
  heightOriginal: number = 0;
  targetWidth: number = 0;
  targetHeight: number = 0;
  blendAlpha: boolean = false;
  colorChannels: number = 0;
  interpolationPass: boolean = false;
  targetWidthMultipliedByChannels: number = 0;
  originalWidthMultipliedByChannels: number = 0;
  originalHeightMultipliedByChannels: number = 0;
  widthPassResultSize: number = 0;
  finalResultSize: number = 0;
  resizeWidth: ((buffer: Float32Array) => Float32Array) | null = null;
  resizeHeight: ((buffer: Float32Array | Uint8Array) => Float32Array | Uint8Array) | null = null;
  ratioWeightWidthPass: number = 0;
  ratioWeightHeightPass: number = 0;
  outputWidthWorkBench: Float32Array = new Float32Array();
  widthBuffer: Float32Array = new Float32Array();
  outputHeightWorkBench: Float32Array = new Float32Array();
  heightBuffer: Uint8Array = new Uint8Array();
  constructor(widthOriginal: number, heightOriginal: number, targetWidth: number, targetHeight: number, blendAlpha: boolean, interpolationPass: boolean) {
    this.blendAlpha = blendAlpha;
    this.widthOriginal = Math.abs(Number.parseInt(String(widthOriginal)) || 0);
    this.heightOriginal = Math.abs(Number.parseInt(String(heightOriginal)) || 0);
    this.targetWidth = Math.abs(Number.parseInt(String(targetWidth)) || 0);
    this.targetHeight = Math.abs(Number.parseInt(String(targetHeight)) || 0);
    this.colorChannels = blendAlpha ? GBEMU_4 : GBEMU_3;
    this.interpolationPass = interpolationPass;
    this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels;
    this.originalWidthMultipliedByChannels = this.widthOriginal * this.colorChannels;
    this.originalHeightMultipliedByChannels = this.heightOriginal * this.colorChannels;
    this.widthPassResultSize = this.targetWidthMultipliedByChannels * this.heightOriginal;
    this.finalResultSize = this.targetWidthMultipliedByChannels * this.targetHeight;
    this.initialize();
  }

  initialize(): void {
    //Perform some checks:
    if (this.widthOriginal > 0 && this.heightOriginal > 0 && this.targetWidth > 0 && this.targetHeight > 0) {
      if (this.widthOriginal === this.targetWidth) {
        //Bypass the width resizer pass:
        this.resizeWidth = this.bypassResizer as (buffer: Float32Array) => Float32Array;
      } else {
        //Setup the width resizer pass:
        this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth;
        if (this.ratioWeightWidthPass < 1 && this.interpolationPass) {
          this.initializeFirstPassBuffers(true);
          this.resizeWidth = this.colorChannels === GBEMU_4 ? this.resizeWidthInterpolatedRGBA : this.resizeWidthInterpolatedRGB;
        } else {
          this.initializeFirstPassBuffers(false);
          this.resizeWidth = this.colorChannels === GBEMU_4 ? this.resizeWidthRGBA : this.resizeWidthRGB;
        }
      }
      if (this.heightOriginal === this.targetHeight) {
        //Bypass the height resizer pass:
        this.resizeHeight = this.bypassResizer;
      } else {
        //Setup the height resizer pass:
        this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight;
        if (this.ratioWeightHeightPass < 1 && this.interpolationPass) {
          this.initializeSecondPassBuffers(true);
          this.resizeHeight = this.resizeHeightInterpolated;
        } else {
          this.initializeSecondPassBuffers(false);
          this.resizeHeight = this.colorChannels === GBEMU_4 ? this.resizeHeightRGBA : this.resizeHeightRGB;
        }
      }
    }
  }

  resizeWidthRGB(buffer: Float32Array): Float32Array {
    let ratioWeight: number = this.ratioWeightWidthPass;
    let weight: number = 0;
    let amountToNext: number = 0;
    let actualPosition: number = 0;
    let currentPosition: number = 0;
    let line: number = 0;
    let pixelOffset: number = 0;
    let outputOffset: number = 0;
    let nextLineOffsetOriginalWidth: number = this.originalWidthMultipliedByChannels - GBEMU_2;
    let nextLineOffsetTargetWidth: number = this.targetWidthMultipliedByChannels - GBEMU_2;
    let output: Float32Array = this.outputWidthWorkBench;
    let outputBuffer: Float32Array = this.widthBuffer;
    do {
      line = 0;
      while (line < this.originalHeightMultipliedByChannels) {
        output[line++] = 0;
        output[line++] = 0;
        output[line++] = 0;
      }
      weight = ratioWeight;
      do {
        amountToNext = 1 + actualPosition - currentPosition;
        if (weight >= amountToNext) {
          line = 0;
          pixelOffset = actualPosition;
          while (line < this.originalHeightMultipliedByChannels) {
            output[line++] += buffer[pixelOffset++] * amountToNext;
            output[line++] += buffer[pixelOffset++] * amountToNext;
            output[line++] += buffer[pixelOffset] * amountToNext;
            pixelOffset += nextLineOffsetOriginalWidth;
          }
          actualPosition = actualPosition + GBEMU_3;
          currentPosition = actualPosition;
          weight -= amountToNext;
        } else {
          line = 0;
          pixelOffset = actualPosition;
          while (line < this.originalHeightMultipliedByChannels) {
            output[line++] += buffer[pixelOffset++] * weight;
            output[line++] += buffer[pixelOffset++] * weight;
            output[line++] += buffer[pixelOffset] * weight;
            pixelOffset += nextLineOffsetOriginalWidth;
          }
          currentPosition += weight;
          break;
        }
      } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels);
      line = 0;
      pixelOffset = outputOffset;
      while (line < this.originalHeightMultipliedByChannels) {
        outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
        outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
        outputBuffer[pixelOffset] = output[line++] / ratioWeight;
        pixelOffset += nextLineOffsetTargetWidth;
      }
      outputOffset += GBEMU_3;
    } while (outputOffset < this.targetWidthMultipliedByChannels);
    return outputBuffer;
  }

  resizeWidthInterpolatedRGB(buffer: Float32Array): Float32Array {
    let ratioWeight: number = (this.widthOriginal - 1) / this.targetWidth;
    let weight: number = 0;
    let finalOffset: number = 0;
    let pixelOffset: number = 0;
    let outputBuffer: Float32Array = this.widthBuffer;
    let targetPosition: number = 0;
    while (targetPosition < this.targetWidthMultipliedByChannels) {
      //Calculate weightings:
      let secondWeight: number = weight % 1;
      let firstWeight: number = 1 - secondWeight;
      //Interpolate:
      finalOffset = targetPosition;
      pixelOffset = Math.floor(weight) * GBEMU_3;
      while (finalOffset < this.widthPassResultSize) {
        outputBuffer[finalOffset] = buffer[pixelOffset] * firstWeight + buffer[pixelOffset + GBEMU_3] * secondWeight;
        outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1] * firstWeight + buffer[pixelOffset + GBEMU_4] * secondWeight;
        outputBuffer[finalOffset + GBEMU_2] = buffer[pixelOffset + GBEMU_2] * firstWeight + buffer[pixelOffset + GBEMU_5] * secondWeight;
        pixelOffset += this.originalWidthMultipliedByChannels;
        finalOffset += this.targetWidthMultipliedByChannels;
      }
      targetPosition += GBEMU_3;
      weight += ratioWeight;
    }
    return outputBuffer;
  }

  resizeWidthInterpolatedRGBA(buffer: Float32Array): Float32Array {
    let ratioWeight: number = (this.widthOriginal - 1) / this.targetWidth;
    let weight: number = 0;
    let finalOffset: number = 0;
    let pixelOffset: number = 0;
    let outputBuffer: Float32Array = this.widthBuffer;
    let targetPosition: number = 0;
    while (targetPosition < this.targetWidthMultipliedByChannels) {
      //Calculate weightings:
      let secondWeight: number = weight % 1;
      let firstWeight: number = 1 - secondWeight;
      //Interpolate:
      finalOffset = targetPosition;
      pixelOffset = Math.floor(weight) * GBEMU_4;
      while (finalOffset < this.widthPassResultSize) {
        outputBuffer[finalOffset] = buffer[pixelOffset] * firstWeight + buffer[pixelOffset + GBEMU_4] * secondWeight;
        outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1] * firstWeight + buffer[pixelOffset + GBEMU_5] * secondWeight;
        outputBuffer[finalOffset + GBEMU_2] = buffer[pixelOffset + GBEMU_2] * firstWeight + buffer[pixelOffset + GBEMU_6] * secondWeight;
        outputBuffer[finalOffset + GBEMU_3] = buffer[pixelOffset + GBEMU_3] * firstWeight + buffer[pixelOffset + GBEMU_7] * secondWeight;
        pixelOffset += this.originalWidthMultipliedByChannels;
        finalOffset += this.targetWidthMultipliedByChannels;
      }
      targetPosition += GBEMU_4;
      weight += ratioWeight;
    }
    return outputBuffer;
  }

  resizeWidthRGBA(buffer: Float32Array): Float32Array {
    let ratioWeight: number = this.ratioWeightWidthPass;
    let weight: number = 0;
    let amountToNext: number = 0;
    let actualPosition: number = 0;
    let currentPosition: number = 0;
    let line: number = 0;
    let pixelOffset: number = 0;
    let outputOffset: number = 0;
    let nextLineOffsetOriginalWidth: number = this.originalWidthMultipliedByChannels - GBEMU_3;
    let nextLineOffsetTargetWidth: number = this.targetWidthMultipliedByChannels - GBEMU_3;
    let output: Float32Array = this.outputWidthWorkBench;
    let outputBuffer: Float32Array = this.widthBuffer;
    do {
      line = 0;
      while (line < this.originalHeightMultipliedByChannels) {
        output[line++] = 0;
        output[line++] = 0;
        output[line++] = 0;
        output[line++] = 0;
      }
      weight = ratioWeight;
      do {
        amountToNext = 1 + actualPosition - currentPosition;
        if (weight >= amountToNext) {
          line = 0;
          pixelOffset = actualPosition;
          while (line < this.originalHeightMultipliedByChannels) {
            output[line++] += buffer[pixelOffset++] * amountToNext;
            output[line++] += buffer[pixelOffset++] * amountToNext;
            output[line++] += buffer[pixelOffset++] * amountToNext;
            output[line++] += buffer[pixelOffset] * amountToNext;
            pixelOffset += nextLineOffsetOriginalWidth;
          }
          actualPosition = actualPosition + GBEMU_4;
          currentPosition = actualPosition;
          weight -= amountToNext;
        } else {
          line = 0;
          pixelOffset = actualPosition;
          while (line < this.originalHeightMultipliedByChannels) {
            output[line++] += buffer[pixelOffset++] * weight;
            output[line++] += buffer[pixelOffset++] * weight;
            output[line++] += buffer[pixelOffset++] * weight;
            output[line++] += buffer[pixelOffset] * weight;
            pixelOffset += nextLineOffsetOriginalWidth;
          }
          currentPosition += weight;
          break;
        }
      } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels);
      line = 0;
      pixelOffset = outputOffset;
      while (line < this.originalHeightMultipliedByChannels) {
        outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
        outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
        outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
        outputBuffer[pixelOffset] = output[line++] / ratioWeight;
        pixelOffset += nextLineOffsetTargetWidth;
      }
      outputOffset += GBEMU_4;
    } while (outputOffset < this.targetWidthMultipliedByChannels);
    return outputBuffer;
  }

  resizeHeightRGB(buffer: Float32Array | Uint8Array): Float32Array | Uint8Array {
    let ratioWeight: number = this.ratioWeightHeightPass;
    let weight: number = 0;
    let amountToNext: number = 0;
    let actualPosition: number = 0;
    let currentPosition: number = 0;
    let pixelOffset: number = 0;
    let outputOffset: number = 0;
    let output: Float32Array = this.outputHeightWorkBench;
    let outputBuffer: Uint8Array = this.heightBuffer;
    do {
      pixelOffset = 0;
      while (pixelOffset < this.targetWidthMultipliedByChannels) {
        output[pixelOffset++] = 0;
        output[pixelOffset++] = 0;
        output[pixelOffset++] = 0;
      }
      weight = ratioWeight;
      do {
        amountToNext = 1 + actualPosition - currentPosition;
        if (weight >= amountToNext) {
          pixelOffset = 0;
          while (pixelOffset < this.targetWidthMultipliedByChannels) {
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
          }
          currentPosition = actualPosition;
          weight -= amountToNext;
        } else {
          pixelOffset = 0;
          amountToNext = actualPosition;
          while (pixelOffset < this.targetWidthMultipliedByChannels) {
            output[pixelOffset++] += buffer[amountToNext++] * weight;
            output[pixelOffset++] += buffer[amountToNext++] * weight;
            output[pixelOffset++] += buffer[amountToNext++] * weight;
          }
          currentPosition += weight;
          break;
        }
      } while (weight > 0 && actualPosition < this.widthPassResultSize);
      pixelOffset = 0;
      while (pixelOffset < this.targetWidthMultipliedByChannels) {
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
      }
    } while (outputOffset < this.finalResultSize);
    return outputBuffer;
  }

  resizeHeightInterpolated(buffer: Uint8Array | Float32Array): Uint8Array | Float32Array {
    let ratioWeight: number = (this.heightOriginal - 1) / this.targetHeight;
    let weight: number = 0;
    let finalOffset: number = 0;
    let pixelOffset: number = 0;
    let pixelOffsetAccumulated: number = 0;
    let pixelOffsetAccumulated2: number = 0;
    let outputBuffer: Uint8Array = this.heightBuffer;
    do {
      //Calculate weightings:
      let secondWeight: number = weight % 1;
      let firstWeight: number = 1 - secondWeight;
      //Interpolate:
      pixelOffsetAccumulated = Math.floor(weight) * this.targetWidthMultipliedByChannels;
      pixelOffsetAccumulated2 = pixelOffsetAccumulated + this.targetWidthMultipliedByChannels;
      pixelOffset = 0;
      while (pixelOffset < this.targetWidthMultipliedByChannels) {
        outputBuffer[finalOffset++] =
          buffer[pixelOffsetAccumulated + pixelOffset] * firstWeight + buffer[pixelOffsetAccumulated2 + pixelOffset] * secondWeight;
        pixelOffset += 1;
      }
      weight += ratioWeight;
    } while (finalOffset < this.finalResultSize);
    return outputBuffer;
  }

  resizeHeightRGBA(buffer: Float32Array | Uint8Array): Float32Array | Uint8Array {
    let ratioWeight: number = this.ratioWeightHeightPass;
    let weight: number = 0;
    let amountToNext: number = 0;
    let actualPosition: number = 0;
    let currentPosition: number = 0;
    let pixelOffset: number = 0;
    let outputOffset: number = 0;
    let output: Float32Array = this.outputHeightWorkBench;
    let outputBuffer: Uint8Array = this.heightBuffer;
    do {
      pixelOffset = 0;
      while (pixelOffset < this.targetWidthMultipliedByChannels) {
        output[pixelOffset++] = 0;
        output[pixelOffset++] = 0;
        output[pixelOffset++] = 0;
        output[pixelOffset++] = 0;
      }
      weight = ratioWeight;
      do {
        amountToNext = 1 + actualPosition - currentPosition;
        if (weight >= amountToNext) {
          pixelOffset = 0;
          while (pixelOffset < this.targetWidthMultipliedByChannels) {
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
            output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
          }
          currentPosition = actualPosition;
          weight -= amountToNext;
        } else {
          pixelOffset = 0;
          amountToNext = actualPosition;
          while (pixelOffset < this.targetWidthMultipliedByChannels) {
            output[pixelOffset++] += buffer[amountToNext++] * weight;
            output[pixelOffset++] += buffer[amountToNext++] * weight;
            output[pixelOffset++] += buffer[amountToNext++] * weight;
            output[pixelOffset++] += buffer[amountToNext++] * weight;
          }
          currentPosition += weight;
          break;
        }
      } while (weight > 0 && actualPosition < this.widthPassResultSize);
      pixelOffset = 0;
      while (pixelOffset < this.targetWidthMultipliedByChannels) {
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
        outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
      }
    } while (outputOffset < this.finalResultSize);
    return outputBuffer;
  }

  resize(buffer: Float32Array | Uint8Array): Float32Array | Uint8Array {
    return this.resizeHeight!(this.resizeWidth!(buffer as Float32Array));
  }

  bypassResizer(buffer: Float32Array | Uint8Array): Float32Array | Uint8Array {
    //Just return the buffer passsed:
    return buffer;
  }

  initializeFirstPassBuffers(biLINEARAlgo: boolean): void {
    //Initialize the internal width pass buffers:
    this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize);
    if (!biLINEARAlgo) {
      this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels);
    }
  }

  initializeSecondPassBuffers(biLINEARAlgo: boolean): void {
    //Initialize the internal height pass buffers:
    this.heightBuffer = this.generateUint8Buffer(this.finalResultSize);
    if (!biLINEARAlgo) {
      this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels);
    }
  }

  generateFloatBuffer(bufferLength: number): Float32Array {
    //Generate a float32 typed array buffer:
    return new Float32Array(bufferLength);
  }

  generateUint8Buffer(bufferLength: number): Uint8Array {
    //Generate a uint8 typed array buffer:
    return new Uint8Array(bufferLength);
  }
}
// End of js/other/resize.js file.

// Remaining files are in gbemu-part2.js, since they run in strict mode.

// ------ gbemu-part2 ------
class GameBoyCore {
  //Params, etc...
  canvas: GameBoyCanvas | null = null; //Canvas DOM object for drawing out the graphics to.
  drawContext: null = null; //LCD Context
  romImage: string; //The game's rom.
  //CPU Registers and Flags:
  registerA = GBEMU_0x01; //Register A (Accumulator)
  fZero: boolean = true; //Register F  - Result was zero
  fSubtract: boolean = false; //Register F  - Subtraction was executed
  fHalfCarry: boolean = true; //Register F  - Half carry or half borrow
  fCarry: boolean = true; //Register F  - Carry or borrow
  registerB: number = GBEMU_0x00; //Register B
  registerC: number = GBEMU_0x13; //Register C
  registerD: number = GBEMU_0x00; //Register D
  registerE: number = GBEMU_0xD8; //Register E
  registerF: number = 0; //Register F
  registersHL: number = GBEMU_0x014D; //Registers H and L combined
  stackPointer: number = GBEMU_0xFFFE; //Stack Pointer
  programCounter: number = GBEMU_0x0100; //Program Counter
  //Some CPU Emulation State Variables:
  cpuCyclesTotal: number = 0; //Relative CPU clocking to speed set, rounded appropriately.
  cpuCyclesTotalBase: number = 0; //Relative CPU clocking to speed set base.
  cpuCyclesTotalCurrent: number = 0; //Relative CPU clocking to speed set, the directly used value.
  cpuCyclesTotalRoundoff: number = 0; //Clocking per iteration rounding catch.
  baseCPUCyclesPerIteration = 0; //CPU clocks per iteration at 1x speed.
  remainingClocks: number = 0; //HALT clocking overrun carry over.
  inBootstrap: boolean = true; //Whether we're in the GBC boot rom.
  usedBootrom: boolean = false; //Updated upon rom loading...
  usedGBCBootrom: boolean = false; //Did we boot to the GBC boot rom?
  halt: boolean = false; //Has the CPU been suspended until the next interrupt?
  skipPCIncrement: boolean = false; //Did we trip the DMG Halt bug?
  stopEmulator: number = GBEMU_3; //Has the emulation been paused or a frame has ended?
  ime: boolean = true; //Are interrupts enabled?
  irqLineMatched: number = 0; //CPU IRQ assertion.
  interruptsRequested: number = 0; //IF Register
  interruptsEnabled: number = 0; //IE Register
  hdmaRunning: boolean = false; //HDMA Transfer Flag - GBC only
  cpuTicks: number = 0; //The number of clock cycles emulated.
  doubleSpeedShifter = 0; //GBC double speed clocking shifter.
  joyPad: number = GBEMU_0xFF; //Joypad State (two four-bit states actually)
  cpuStopped: boolean = false; //CPU STOP status.
  //Main RAM, MBC RAM, GBC Main RAM, vram, etc.
  memoryReader: Array<(parentObj: GameBoyCore, address: number) => number> = []; //Array of functions mapped to read back memory
  memoryWriter: Array<(parentObj: GameBoyCore, address: number, data: number) => void> = []; //Array of functions mapped to write to memory
  memoryHighReader: Array<(parentObj: GameBoyCore, address: number) => number> = []; //Array of functions mapped to read back 0xFFXX memory
  memoryHighWriter: Array<(parentObj: GameBoyCore, address: number, data: number) => void> = []; //Array of functions mapped to write to 0xFFXX memory
  rom: TNextArray = new Int8Array(); //The full rom file dumped to an array.
  memory: TNextArray = new Int8Array(); //Main Core Memory
  mbcRam: TNextArray = new Int8Array(); //Switchable RAM (Used by games for more RAM) for the main memory range 0xA000 - 0xC000.
  vram: TNextArray | null = new Int8Array(); //Extra vram bank for GBC.
  gbcMemory: TNextArray | null = new Int8Array(); //GBC main RAM Banks
  mbc1Mode: boolean = false; //MBC1 Type (GBEMU_4/GBEMU_32, GBEMU_16/GBEMU_8)
  mbcRamBanksEnabled: boolean = false; //MBC RAM Access Control.
  currMBCRAMBank: number = 0; //MBC Currently Indexed RAM Bank
  currMBCRAMBankPosition = -GBEMU_0xA000; //MBC Position Adder;
  cGBC: boolean = false; //GameBoy Color detection.
  gbcRamBank: number = 1; //Currently Switched GameBoy Color ram bank
  gbcRamBankPosition = -GBEMU_0xD000; //GBC RAM offset from address start.
  gbcRamBankPositionECHO = -GBEMU_0xF000; //GBC RAM (ECHO mirroring) offset from address start.
  ramBanks: number[] = [0, 1, GBEMU_2, GBEMU_4, GBEMU_16]; //Used to map the RAM banks to maximum size the MBC used can do.
  romBank1offs: number = 0; //Offset of the rom bank switching.
  currentromBank: number = 0; //The parsed current rom bank selection.
  cartridgeType: number = 0; //Cartridge Type
  name: string = ''; //Name of the game
  gameCode: string = ''; //Game code (Suffix for older games)
  fromSaveState: boolean = false; //A boolean to see if this was loaded in as a save state.
  savedStateFileName = ''; //When loaded in as a save state, this will not be empty.
  statTracker: number = 0; //Tracker for STAT triggering.
  modeSTAT: number = 0; //The scan line mode (for lines 1-144 it's GBEMU_2-GBEMU_3-0, for 145-154 it's 1)
  spriteCount: number = GBEMU_252; //Mode GBEMU_3 extra clocking counter (Depends on how many sprites are on the current line.).
  lycMatchTriggerSTAT: boolean = false; //Should we trigger an interrupt if LY==LYC?
  mode2TriggerSTAT: boolean = false; //Should we trigger an interrupt if in mode GBEMU_2?
  mode1TriggerSTAT: boolean = false; //Should we trigger an interrupt if in mode 1?
  mode0TriggerSTAT: boolean = false; //Should we trigger an interrupt if in mode 0?
  lcdIsOn: boolean = false; //Is the emulated LCD controller on?
  lineControl: Array<(parentObj: GameBoyCore) => void> = []; //Array of functions to handle each scan line we do (onscreen + offscreen)
  disPlayOffControl: Array<(parentObj: GameBoyCore) => void> = [
    parentObj => {
      //Array of line 0 function to handle the LCD controller when it's off (Do nothing!).
    }
  ];
  lcdControl: Array<(parentObj: GameBoyCore) => void> = []; //Pointer to either lineControl or disPlayOffControl.
  //RTC (Real Time Clock for MBC3):
  rtcIsLatched: boolean = false;
  latchedSeconds: number = 0; //RTC latched seconds.
  latchedMinutes: number = 0; //RTC latched minutes.
  latchedHours: number = 0; //RTC latched hours.
  latchedLDays: number = 0; //RTC latched lower GBEMU_8-bits of the day counter.
  latchedHDays: number = 0; //RTC latched high-bit of the day counter.
  rtcSeconds: number = 0; //RTC seconds counter.
  rtcMinutes: number = 0; //RTC minutes counter.
  rtcHours: number = 0; //RTC hours counter.
  rtcDays: number = 0; //RTC days counter.
  rtcDayOverFlow: boolean = false; //Did the RTC overflow and wrap the day counter?
  rtcHalt: boolean = false; //Is the RTC allowed to clock up?
  //Gyro:
  highX: number = GBEMU_127;
  lowX: number = GBEMU_127;
  highY: number = GBEMU_127;
  lowY: number = GBEMU_127;
  //Sound variables:
  audioHandle: XAudioServer | null = null; //XAudioJS handle
  numSamplesTotal: number = 0; //Length of the sound buffers.
  sampleSize: number = 0; //Length of the sound buffer for one channel.
  dutyLookup: boolean[][] = [
    //Map the duty values given to ones we can work with.
    [false, false, false, false, false, false, false, true], [true, false, false, false, false, false, false, true], [true, false, false, false, false, true, true, true], [false, true, true, true, true, true, true, false]
  ];
  currentBuffer: TNextArray = new Int8Array(); //The audio buffer we're working on.
  secondaryBuffer: TNextArray = new Int8Array();
  bufferContainAmount: number = 0; //Buffer maintenance metric.
  lsfr15Table: TNextArray | null = new Int8Array();
  lsfr7Table: TNextArray | null = new Int8Array();
  noiseSampleTable: TNextArray | null = new Int8Array();

  soundMasterEnabled: boolean = false; //As its name implies
  channel3PCM: TNextArray | null = new Int8Array(); //Channel GBEMU_3 adjusted sample buffer.
  //Vin Shit:
  vinLeftChannelMasterVolume = GBEMU_8; //Computed post-mixing volume.
  vinRightChannelMasterVolume = GBEMU_8; //Computed post-mixing volume.
  //Channel paths enabled:
  leftChannel1: boolean = false;
  leftChannel2: boolean = false;
  leftChannel3: boolean = false;
  leftChannel4: boolean = false;
  rightChannel1: boolean = false;
  rightChannel2: boolean = false;
  rightChannel3: boolean = false;
  rightChannel4: boolean = false;
  //Channel output level caches:
  channel1currentSampleLeft: number = 0;
  channel1currentSampleRight: number = 0;
  channel2currentSampleLeft: number = 0;
  channel2currentSampleRight: number = 0;
  channel3currentSampleLeft: number = 0;
  channel3currentSampleRight: number = 0;
  channel4currentSampleLeft: number = 0;
  channel4currentSampleRight: number = 0;
  channel1currentSampleLeftSecondary: number = 0;
  channel1currentSampleRightSecondary: number = 0;
  channel2currentSampleLeftSecondary: number = 0;
  channel2currentSampleRightSecondary: number = 0;
  channel3currentSampleLeftSecondary: number = 0;
  channel3currentSampleRightSecondary: number = 0;
  channel4currentSampleLeftSecondary: number = 0;
  channel4currentSampleRightSecondary: number = 0;
  channel1currentSampleLeftTrimary: number = 0;
  channel1currentSampleRightTrimary: number = 0;
  channel2currentSampleLeftTrimary: number = 0;
  channel2currentSampleRightTrimary: number = 0;
  mixerOutputCache: number = 0;
  //Pre-multipliers to cache some calculations:
  machineOut: number = 0; //Premultiplier for audio samples per instruction.
  //Audio generation counters:
  audioTicks: number = 0; //Used to sample the audio system every x CPU instructions.
  audioIndex: number = 0; //Used to keep alignment on audio generation.
  rollover: number = 0; //Used to keep alignment on the number of samples to output (Realign from counter alias).
  //Timing Variables
  emulatorTicks: number = 0; //Times for how many instructions to execute before ending the loop.
  divTicks: number = GBEMU_56; //DIV Ticks Counter (Invisible lower GBEMU_8-bit)
  lcdTicks: number = GBEMU_60; //Counter for how many instructions have been executed on a scanline so far.
  timerTicks: number = 0; //Counter for the TIMA timer.
  timaEnabled: boolean = false; //Is TIMA enabled?
  tacClocker: number = GBEMU_1024; //Timer Max Ticks
  serialTimer: number = 0; //Serial IRQ Timer
  serialShiftTimer: number = 0; //Serial Transfer Shift Timer
  serialShiftTimerAllocated: number = 0; //Serial Transfer Shift Timer Refill
  irqEnableDelay: number = 0; //Are the interrupts on queue to be enabled?
  lastIteration: number = new NewDate().getTime(); //The last time we iterated the main loop.
  firstIteration: number = new NewDate().getTime(); //The line is changed for benchmarking.
  iterations: number = 0;
  actualScanLine: number = 0; //Actual scan line...
  lastUnrenderedLine: number = 0; //Last rendered scan line...
  queuedScanLines: number = 0;
  totalLinesPassed: number = 0;
  haltPostClocks: number = 0; //Post-Halt clocking.
  //rom Cartridge Components:
  cMBC1: boolean = false; //Does the cartridge use MBC1?
  cMBC2: boolean = false; //Does the cartridge use MBC2?
  cMBC3: boolean = false; //Does the cartridge use MBC3?
  cMBC5: boolean = false; //Does the cartridge use MBC5?
  cMBC7: boolean = false; //Does the cartridge use MBC7?
  cSRAM: boolean = false; //Does the cartridge use save RAM?
  cMMMO1: boolean = false; //...
  cRUMBLE: boolean = false; //Does the cartridge use the RUMBLE addressing (modified MBC5)?
  cCamera: boolean = false; //Is the cartridge actually a GameBoy Camera?
  cTAMA5: boolean = false; //Does the cartridge use TAMA5? (Tamagotchi Cartridge)
  cHuC3: boolean = false; //Does the cartridge use HuC3 (Hudson Soft / modified MBC3)?
  cHuC1: boolean = false; //Does the cartridge use HuC1 (Hudson Soft / modified MBC1)?
  cTimeR: boolean = false; //Does the cartridge have an RTC?
  romBanks: Map<number, number> = new Map([
    //1 Bank = GBEMU_16 KBytes = 256 Kbits
    [0, GBEMU_2], [1, GBEMU_4], [GBEMU_2, GBEMU_8], [GBEMU_3, GBEMU_16], [GBEMU_4, GBEMU_32], [GBEMU_5, GBEMU_64], [GBEMU_6, GBEMU_128], [GBEMU_7, GBEMU_256], [GBEMU_8, GBEMU_512], [GBEMU_0x52, GBEMU_72], [GBEMU_0x53, GBEMU_80], [GBEMU_0x54, GBEMU_96]
  ]);
  numRamBanks: number = 0; //How many RAM banks were actually allocated?
  //Graphics Variables
  currvramBank: number = 0; //Current vram bank for GBC.
  backgroundX: number = 0; //Register SCX (X-Scroll)
  backgroundY: number = 0; //Register SCY (Y-Scroll)
  gfxWindowDisplay: boolean = false; //Is the windows enabled?
  gfxSpriteShow: boolean = false; //Are sprites enabled?
  gfxSpriteNormalHeight: boolean = true; //Are we doing 8x8 or 8x16 sprites?
  bgEnabled: boolean = true; //Is the BG enabled?
  bgPriorityEnabled: boolean = true; //Can we flag the BG for priority over sprites?
  gfxWindowCHRBankPosition: number = 0; //The current bank of the character map the window uses.
  gfxBackgroundCHRBankPosition: number = 0; //The current bank of the character map the BG uses.
  gfxBackgroundBankOffset = GBEMU_0x80; //Fast mapping of the tile numbering/
  windowY: number = 0; //Current Y offset of the window.
  windowX: number = 0; //Current X offset of the window.
  drewBlank: number = 0; //To prevent the repeating of drawing a blank screen.
  drewFrame: boolean = false; //Throttle how many draws we can do to once per iteration.
  midScanlineOffset = -1; //mid-scanline rendering offset.
  pixelEnd: number = 0; //track the x-coord limit for line rendering (mid-scanline usage).
  currentX: number = 0; //The x-coord we left off at for mid-scanline rendering.
  //BG Tile Pointer Caches:
  bgCHRBank1: ArrayObject = new ArrayObject();
  bgCHRBank2: ArrayObject = new ArrayObject();
  bgCHRCurrentBank: ArrayObject | null = null;
  //Tile Data Cache:
  tileCache: Array<ArrayObject> | null = [];
  //Palettes:
  colors: number[] = [GBEMU_0xEFFFDE, GBEMU_0xADD794, GBEMU_0x529273, GBEMU_0x183442]; //'Classic' GameBoy palette colors.
  objPalette: TNextArray | null = new Int32Array();
  bgPalette: TNextArray | null = new Int32Array();
  gbcOBJRawPalette: TNextArray | null = new Int32Array();
  gbcBGRawPalette: TNextArray | null = new Int32Array();
  gbOBJPalette: TNextArray | null = new Int32Array();
  gbBGPalette: TNextArray | null = new Int32Array();
  gbcOBJPalette: TNextArray | null = new Int32Array();
  gbcBGPalette: TNextArray | null = new Int32Array();
  gbBGColorizedPalette: TNextArray | null = new Int32Array();
  gbOBJColorizedPalette: TNextArray | null = new Int32Array();
  cachedBGPaletteConversion: TNextArray | null = new Int32Array();
  cachedOBJPaletteConversion: TNextArray | null = new Int32Array();
  updateGBBGPalette: ((data: number) => void) | null = null;
  updateGBOBJPalette: ((address: number, data: number) => void) | null = null;
  colorizedGBPalettes: boolean = false;
  bgLayerRender: ((data: number) => void) | null = null; //Reference to the BG rendering function.
  windowLayerRender: ((data: number) => void) | null = null; //Reference to the window rendering function.
  spriteLayerRender: ((data: number) => void) | null = null; //Reference to the OAM rendering function.
  frameBuffer: TNextArray = new Int8Array(); //The internal frame-buffer.
  swizzledFrame: TNextArray | null = new Int8Array(); //The secondary gfx buffer that holds the converted RGBA values.
  canvasBuffer: GameBoyContextImageDataResult | null = null; //imageData handle
  pixelStart: number = 0; //Temp variable for holding the current working framebuffer offset.
  //Variables used for scaling in JS:
  onscreenWidth: number = GBEMU_160;
  offscreenWidth: number = GBEMU_160;
  onscreenHeight: number = GBEMU_144;
  offscreenHeight: number = GBEMU_144;
  offscreenRGBCount: number = this.onscreenWidth * this.onscreenHeight * GBEMU_4;

  // Start of code changed for benchmarking (removed rom):
  gbBOOTrom: TNextArray = [] as Object as TNextArray;
  gbCBOOTrom: TNextArray = [] as Object as TNextArray;
  // End of code changed for benchmarking.

  ffxxDump: number[] = [
    //Dump of the post-BOOT I/O register state (From gambatte):
    GBEMU_0x0F, GBEMU_0x00, GBEMU_0x7C, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xF8, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x01, GBEMU_0x80, GBEMU_0xBF, GBEMU_0xF3, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0xFF, GBEMU_0x3F, GBEMU_0x00, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0x7F, GBEMU_0xFF, GBEMU_0x9F, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0xBF, GBEMU_0x77, GBEMU_0xF3, GBEMU_0xF1, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x91, GBEMU_0x80, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFC, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x7E, GBEMU_0xFF, GBEMU_0xFE, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x3E, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xC0, GBEMU_0xFF, GBEMU_0xC1, GBEMU_0x00, GBEMU_0xFE, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xF8, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x8F, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xCE, GBEMU_0xED, GBEMU_0x66, GBEMU_0x66, GBEMU_0xCC, GBEMU_0x0D, GBEMU_0x00, GBEMU_0x0B, GBEMU_0x03, GBEMU_0x73, GBEMU_0x00, GBEMU_0x83, GBEMU_0x00, GBEMU_0x0C, GBEMU_0x00, GBEMU_0x0D, GBEMU_0x00, GBEMU_0x08, GBEMU_0x11, GBEMU_0x1F, GBEMU_0x88, GBEMU_0x89, GBEMU_0x00, GBEMU_0x0E, GBEMU_0xDC, GBEMU_0xCC, GBEMU_0x6E, GBEMU_0xE6, GBEMU_0xDD, GBEMU_0xDD, GBEMU_0xD9, GBEMU_0x99, GBEMU_0xBB, GBEMU_0xBB, GBEMU_0x67, GBEMU_0x63, GBEMU_0x6E, GBEMU_0x0E, GBEMU_0xEC, GBEMU_0xCC, GBEMU_0xDD, GBEMU_0xDC, GBEMU_0x99, GBEMU_0x9F, GBEMU_0xBB, GBEMU_0xB9, GBEMU_0x33, GBEMU_0x3E, GBEMU_0x45, GBEMU_0xEC, GBEMU_0x52, GBEMU_0xFA, GBEMU_0x08, GBEMU_0xB7, GBEMU_0x07, GBEMU_0x5D, GBEMU_0x01, GBEMU_0xFD, GBEMU_0xC0, GBEMU_0xFF, GBEMU_0x08, GBEMU_0xFC, GBEMU_0x00, GBEMU_0xE5, GBEMU_0x0B, GBEMU_0xF8, GBEMU_0xC2, GBEMU_0xCE, GBEMU_0xF4, GBEMU_0xF9, GBEMU_0x0F, GBEMU_0x7F, GBEMU_0x45, GBEMU_0x6D, GBEMU_0x3D, GBEMU_0xFE, GBEMU_0x46, GBEMU_0x97, GBEMU_0x33, GBEMU_0x5E, GBEMU_0x08, GBEMU_0xEF, GBEMU_0xF1, GBEMU_0xFF, GBEMU_0x86, GBEMU_0x83, GBEMU_0x24, GBEMU_0x74, GBEMU_0x12, GBEMU_0xFC, GBEMU_0x00, GBEMU_0x9F, GBEMU_0xB4, GBEMU_0xB7, GBEMU_0x06, GBEMU_0xD5, GBEMU_0xD0, GBEMU_0x7A, GBEMU_0x00, GBEMU_0x9E, GBEMU_0x04, GBEMU_0x5F, GBEMU_0x41, GBEMU_0x2F, GBEMU_0x1D, GBEMU_0x77, GBEMU_0x36, GBEMU_0x75, GBEMU_0x81, GBEMU_0xAA, GBEMU_0x70, GBEMU_0x3A, GBEMU_0x98, GBEMU_0xD1, GBEMU_0x71, GBEMU_0x02, GBEMU_0x4D, GBEMU_0x01, GBEMU_0xC1, GBEMU_0xFF, GBEMU_0x0D, GBEMU_0x00, GBEMU_0xD3, GBEMU_0x05, GBEMU_0xF9, GBEMU_0x00, GBEMU_0x0B, GBEMU_0x00
  ];

  // other perpty
  channel1FrequencyTracker: number = GBEMU_0x2000;
  channel1DutyTracker: number = 0;
  channel1CachedDuty: boolean[] = [];
  channel1totalLength: number = 0;
  channel1envelopeVolume: number = 0;
  channel1envelopeType: boolean = false;
  channel1envelopeSweeps: number = 0;
  channel1envelopeSweepsLast: number = 0;
  channel1consecutive: boolean = true;
  channel1frequency: number = GBEMU_1985;
  channel1SweepFault: boolean = true;
  channel1ShadowFrequency: number = GBEMU_1985;
  channel1timeSweep: number = 1;
  channel1lastTimeSweep: number = 0;
  channel1numSweep: number = 0;
  channel1frequencySweepDivider: number = 0;
  channel1decreaseSweep: boolean = false;
  channel2FrequencyTracker: number = GBEMU_0x2000;
  channel2DutyTracker: number = 0;
  channel2CachedDuty: boolean[] = [];
  channel2totalLength: number = 0;
  channel2envelopeVolume: number = 0;
  channel2envelopeType: boolean = false;
  channel2envelopeSweeps: number = 0;
  channel2envelopeSweepsLast: number = 0;
  channel2consecutive: boolean = true;
  channel2frequency: number = 0;
  channel3canPlay: boolean = false;
  channel3totalLength: number = 0;
  channel3patternType: number = GBEMU_4;
  channel3frequency: number = 0;
  channel3consecutive: boolean = true;
  channel3Counter: number = GBEMU_0x418;
  channel4FrequencyPeriod: number = GBEMU_8;
  channel4totalLength: number = 0;
  channel4envelopeVolume: number = 0;
  channel4currentVolume: number = 0;
  channel4envelopeType: boolean = false;
  channel4envelopeSweeps: number = 0;
  channel4envelopeSweepsLast: number = 0;
  channel4consecutive: boolean = true;
  channel4BitRange: number = GBEMU_0x7FFF;
  channel4VolumeShifter: number = GBEMU_15;
  channel1FrequencyCounter: number = GBEMU_0x200;
  channel2FrequencyCounter: number = GBEMU_0x200;
  channel3FrequencyPeriod: number = GBEMU_0x800;
  channel3lastSampleLookup: number = 0;
  channel4lastSampleLookup: number = 0;
  sequencerClocks: number = GBEMU_0x2000;
  sequencePosition: number = 0;
  channel4Counter: number = GBEMU_8;
  cachedChannel3Sample: number = 0;
  cachedChannel4Sample: number = 0;
  channel1Enabled: boolean = false;
  channel2Enabled: boolean = false;
  channel3Enabled: boolean = false;
  channel4Enabled: boolean = false;
  channel1canPlay: boolean = false;
  channel2canPlay: boolean = false;
  channel4canPlay: boolean = false;
  romBankEdge: number = 0;
  cBATT: boolean = false;
  oamAddressCache: TNextArray = new Int32Array(GBEMU_10);
  sortBuffer: TNextArray = new Int8Array(GBEMU_0x100);
  resizer: Resize | null = null;
  instructions: number = 0;
  totalInstructions: number = 0;
  drawContextOnscreen: GameBoyContext | null = null;
  drawContextOffscreen: GameBoyContext | null = null;
  canvasOffscreen: GameBoyCanvas | null = null;
  openMBC: (name: string) => number[] = (name: string): number[] => [];
  openRTC: (filename: string) => Array<number | boolean> = (filename: string): Array<number | boolean> => [];
  numRomBanks: number = 0;

  opCode: Array<(parentObj: GameBoyCore) => void> = [
    //NOP
    //#0x00:
    parentObj => {
      //Do Nothing...
    },
    //LD BC, nn
    //#0x01:
    parentObj => {
      parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.registerB = parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LD (BC), A
    //#0x02:
    parentObj => {
      parentObj.memoryWrite((parentObj.registerB << GBEMU_8) | parentObj.registerC, parentObj.registerA);
    },
    //INC BC
    //#0x03:
    parentObj => {
      let tempVar = ((parentObj.registerB << GBEMU_8) | parentObj.registerC) + 1;
      parentObj.registerB = (tempVar >> GBEMU_8) & GBEMU_0xFF;
      parentObj.registerC = tempVar & GBEMU_0xFF;
    },
    //INC B
    //#0x04:
    parentObj => {
      parentObj.registerB = (parentObj.registerB + 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerB === 0;
      parentObj.fHalfCarry = (parentObj.registerB & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
    },
    //DEC B
    //#0x05:
    parentObj => {
      parentObj.registerB = (parentObj.registerB - 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerB === 0;
      parentObj.fHalfCarry = (parentObj.registerB & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
    },
    //LD B, n
    //#0x06:
    parentObj => {
      parentObj.registerB = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //RLCA
    //#0x07:
    parentObj => {
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.registerA >> GBEMU_7);
      parentObj.fZero = false;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //LD (nn), SP
    //#0x08:
    parentObj => {
      let tempVar =
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      parentObj.memoryWrite(tempVar, parentObj.stackPointer & GBEMU_0xFF);
      parentObj.memoryWrite((tempVar + 1) & GBEMU_0xFFFF, parentObj.stackPointer >> GBEMU_8);
    },
    //ADD HL, BC
    //#0x09:
    parentObj => {
      let dirtySum = parentObj.registersHL + ((parentObj.registerB << GBEMU_8) | parentObj.registerC);
      parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
      parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
      parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
      parentObj.fSubtract = false;
    },
    //LD A, (BC)
    //#0x0A:
    parentObj => {
      parentObj.registerA = parentObj.memoryRead((parentObj.registerB << GBEMU_8) | parentObj.registerC);
    },
    //DEC BC
    //#0x0B:
    parentObj => {
      let tempVar = (((parentObj.registerB << GBEMU_8) | parentObj.registerC) - 1) & GBEMU_0xFFFF;
      parentObj.registerB = tempVar >> GBEMU_8;
      parentObj.registerC = tempVar & GBEMU_0xFF;
    },
    //INC C
    //#0x0C:
    parentObj => {
      parentObj.registerC = (parentObj.registerC + 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerC === 0;
      parentObj.fHalfCarry = (parentObj.registerC & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
    },
    //DEC C
    //#0x0D:
    parentObj => {
      parentObj.registerC = (parentObj.registerC - 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerC === 0;
      parentObj.fHalfCarry = (parentObj.registerC & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
    },
    //LD C, n
    //#0x0E:
    parentObj => {
      parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //RRCA
    //#0x0F:
    parentObj => {
      parentObj.registerA = (parentObj.registerA >> 1) | ((parentObj.registerA & 1) << GBEMU_7);
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.fZero = false;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //STOP
    //#0x10:
    parentObj => {
      if (parentObj.cGBC) {
        if ((parentObj.memory[GBEMU_0xFF4D] & GBEMU_0x01) === GBEMU_0x01) {
          //Speed change requested.
          if (parentObj.memory[GBEMU_0xFF4D] > GBEMU_0x7F) {
            //Go back to single speed mode.
            cout('Going into single clock speed mode.', 0);
            parentObj.doubleSpeedShifter = 0;
            parentObj.memory[GBEMU_0xFF4D] &= GBEMU_0x7F; //Clear the double speed mode flag.
          } else {
            //Go to double speed mode.
            cout('Going into double clock speed mode.', 0);
            parentObj.doubleSpeedShifter = 1;
            parentObj.memory[GBEMU_0xFF4D] |= GBEMU_0x80; //Set the double speed mode flag.
          }
          parentObj.memory[GBEMU_0xFF4D] &= GBEMU_0xFE; //Reset the request bit.
        } else {
          parentObj.handleSTOP(); //Handle Stop
        }
      } else {
        parentObj.handleSTOP();
      }
    },
    //LD DE, nn
    //#0x11:
    parentObj => {
      parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.registerD = parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LD (DE), A
    //#0x12:
    parentObj => {
      parentObj.memoryWrite((parentObj.registerD << GBEMU_8) | parentObj.registerE, parentObj.registerA);
    },
    //INC DE
    //#0x13:
    parentObj => {
      let tempVar = ((parentObj.registerD << GBEMU_8) | parentObj.registerE) + 1;
      parentObj.registerD = (tempVar >> GBEMU_8) & GBEMU_0xFF;
      parentObj.registerE = tempVar & GBEMU_0xFF;
    },
    //INC D
    //#0x14:
    parentObj => {
      parentObj.registerD = (parentObj.registerD + 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerD === 0;
      parentObj.fHalfCarry = (parentObj.registerD & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
    },
    //DEC D
    //#0x15:
    parentObj => {
      parentObj.registerD = (parentObj.registerD - 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerD === 0;
      parentObj.fHalfCarry = (parentObj.registerD & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
    },
    //LD D, n
    //#0x16:
    parentObj => {
      parentObj.registerD = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //RLA
    //#0x17:
    parentObj => {
      let carry_flag = parentObj.fCarry ? 1 : 0;
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | carry_flag;
      parentObj.fZero = false;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //JR n
    //#0x18:
    parentObj => {
      parentObj.programCounter =
        (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
        GBEMU_0xFFFF;
    },
    //ADD HL, DE
    //#0x19:
    parentObj => {
      let dirtySum = parentObj.registersHL + ((parentObj.registerD << GBEMU_8) | parentObj.registerE);
      parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
      parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
      parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
      parentObj.fSubtract = false;
    },
    //LD A, (DE)
    //#0x1A:
    parentObj => {
      parentObj.registerA = parentObj.memoryRead((parentObj.registerD << GBEMU_8) | parentObj.registerE);
    },
    //DEC DE
    //#0x1B:
    parentObj => {
      let tempVar = (((parentObj.registerD << GBEMU_8) | parentObj.registerE) - 1) & GBEMU_0xFFFF;
      parentObj.registerD = tempVar >> GBEMU_8;
      parentObj.registerE = tempVar & GBEMU_0xFF;
    },
    //INC E
    //#0x1C:
    parentObj => {
      parentObj.registerE = (parentObj.registerE + 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerE === 0;
      parentObj.fHalfCarry = (parentObj.registerE & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
    },
    //DEC E
    //#0x1D:
    parentObj => {
      parentObj.registerE = (parentObj.registerE - 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerE === 0;
      parentObj.fHalfCarry = (parentObj.registerE & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
    },
    //LD E, n
    //#0x1E:
    parentObj => {
      parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //RRA
    //#0x1F:
    parentObj => {
      let carry_flag = parentObj.fCarry ? GBEMU_0x80 : 0;
      parentObj.fCarry = (parentObj.registerA & 1) === 1;
      parentObj.registerA = (parentObj.registerA >> 1) | carry_flag;
      parentObj.fZero = false;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //JR NZ, n
    //#0x20:
    parentObj => {
      if (!parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
          GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      }
    },
    //LD HL, nn
    //#0x21:
    parentObj => {
      parentObj.registersHL =
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LDI (HL), A
    //#0x22:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
      parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
    },
    //INC HL
    //#0x23:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
    },
    //INC H
    //#0x24:
    parentObj => {
      let h = ((parentObj.registersHL >> GBEMU_8) + 1) & GBEMU_0xFF;
      parentObj.fZero = h === 0;
      parentObj.fHalfCarry = (h & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
      parentObj.registersHL = (h << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //DEC H
    //#0x25:
    parentObj => {
      let h = ((parentObj.registersHL >> GBEMU_8) - 1) & GBEMU_0xFF;
      parentObj.fZero = h === 0;
      parentObj.fHalfCarry = (h & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
      parentObj.registersHL = (h << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, n
    //#0x26:
    parentObj => {
      parentObj.registersHL =
        (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //DAA
    //#0x27:
    parentObj => {
      if (!parentObj.fSubtract) {
        if (parentObj.fCarry || parentObj.registerA > GBEMU_0x99) {
          parentObj.registerA = (parentObj.registerA + GBEMU_0x60) & GBEMU_0xFF;
          parentObj.fCarry = true;
        }
        if (parentObj.fHalfCarry || (parentObj.registerA & GBEMU_0xF) > GBEMU_0x9) {
          parentObj.registerA = (parentObj.registerA + GBEMU_0x06) & GBEMU_0xFF;
          parentObj.fHalfCarry = false;
        }
      } else if (parentObj.fCarry && parentObj.fHalfCarry) {
        parentObj.registerA = (parentObj.registerA + GBEMU_0x9A) & GBEMU_0xFF;
        parentObj.fHalfCarry = false;
      } else if (parentObj.fCarry) {
        parentObj.registerA = (parentObj.registerA + GBEMU_0xA0) & GBEMU_0xFF;
      } else if (parentObj.fHalfCarry) {
        parentObj.registerA = (parentObj.registerA + GBEMU_0xFA) & GBEMU_0xFF;
        parentObj.fHalfCarry = false;
      }
      parentObj.fZero = parentObj.registerA === 0;
    },
    //JR Z, n
    //#0x28:
    parentObj => {
      if (parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
          GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      }
    },
    //ADD HL, HL
    //#0x29:
    parentObj => {
      parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > GBEMU_0x7FF;
      parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
      parentObj.registersHL = (parentObj.registersHL << 1) & GBEMU_0xFFFF;
      parentObj.fSubtract = false;
    },
    //LDI A, (HL)
    //#0x2A:
    parentObj => {
      parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
    },
    //DEC HL
    //#0x2B:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
    },
    //INC L
    //#0x2C:
    parentObj => {
      let L = (parentObj.registersHL + 1) & GBEMU_0xFF;
      parentObj.fZero = L === 0;
      parentObj.fHalfCarry = (L & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | L;
    },
    //DEC L
    //#0x2D:
    parentObj => {
      let L = (parentObj.registersHL - 1) & GBEMU_0xFF;
      parentObj.fZero = L === 0;
      parentObj.fHalfCarry = (L & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | L;
    },
    //LD L, n
    //#0x2E:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //CPL
    //#0x2F:
    parentObj => {
      parentObj.registerA ^= GBEMU_0xFF;
      parentObj.fSubtract = true;
      parentObj.fHalfCarry = true;
    },
    //JR NC, n
    //#0x30:
    parentObj => {
      if (!parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
          GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      }
    },
    //LD SP, nn
    //#0x31:
    parentObj => {
      parentObj.stackPointer =
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LDD (HL), A
    //#0x32:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
      parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
    },
    //INC SP
    //#0x33:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer + 1) & GBEMU_0xFFFF;
    },
    //INC (HL)
    //#0x34:
    parentObj => {
      let tempVar = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) + 1) & GBEMU_0xFF;
      parentObj.fZero = tempVar === 0;
      parentObj.fHalfCarry = (tempVar & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
    },
    //DEC (HL)
    //#0x35:
    parentObj => {
      let tempVar = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) - 1) & GBEMU_0xFF;
      parentObj.fZero = tempVar === 0;
      parentObj.fHalfCarry = (tempVar & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
    },
    //LD (HL), n
    //#0x36:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)
      );
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //SCF
    //#0x37:
    parentObj => {
      parentObj.fCarry = true;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //JR C, n
    //#0x38:
    parentObj => {
      if (parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
          GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      }
    },
    //ADD HL, SP
    //#0x39:
    parentObj => {
      let dirtySum = parentObj.registersHL + parentObj.stackPointer;
      parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
      parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
      parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
      parentObj.fSubtract = false;
    },
    //LDD A, (HL)
    //#0x3A:
    parentObj => {
      parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
    },
    //DEC SP
    //#0x3B:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
    },
    //INC A
    //#0x3C:
    parentObj => {
      parentObj.registerA = (parentObj.registerA + 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) === 0;
      parentObj.fSubtract = false;
    },
    //DEC A
    //#0x3D:
    parentObj => {
      parentObj.registerA = (parentObj.registerA - 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) === GBEMU_0xF;
      parentObj.fSubtract = true;
    },
    //LD A, n
    //#0x3E:
    parentObj => {
      parentObj.registerA = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //CCF
    //#0x3F:
    parentObj => {
      parentObj.fCarry = !parentObj.fCarry;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
    },
    //LD B, B
    //#0x40:
    parentObj => {
      //Do nothing...
    },
    //LD B, C
    //#0x41:
    parentObj => {
      parentObj.registerB = parentObj.registerC;
    },
    //LD B, D
    //#0x42:
    parentObj => {
      parentObj.registerB = parentObj.registerD;
    },
    //LD B, E
    //#0x43:
    parentObj => {
      parentObj.registerB = parentObj.registerE;
    },
    //LD B, H
    //#0x44:
    parentObj => {
      parentObj.registerB = parentObj.registersHL >> GBEMU_8;
    },
    //LD B, L
    //#0x45:
    parentObj => {
      parentObj.registerB = parentObj.registersHL & GBEMU_0xFF;
    },
    //LD B, (HL)
    //#0x46:
    parentObj => {
      parentObj.registerB = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD B, A
    //#0x47:
    parentObj => {
      parentObj.registerB = parentObj.registerA;
    },
    //LD C, B
    //#0x48:
    parentObj => {
      parentObj.registerC = parentObj.registerB;
    },
    //LD C, C
    //#0x49:
    parentObj => {
      //Do nothing...
    },
    //LD C, D
    //#0x4A:
    parentObj => {
      parentObj.registerC = parentObj.registerD;
    },
    //LD C, E
    //#0x4B:
    parentObj => {
      parentObj.registerC = parentObj.registerE;
    },
    //LD C, H
    //#0x4C:
    parentObj => {
      parentObj.registerC = parentObj.registersHL >> GBEMU_8;
    },
    //LD C, L
    //#0x4D:
    parentObj => {
      parentObj.registerC = parentObj.registersHL & GBEMU_0xFF;
    },
    //LD C, (HL)
    //#0x4E:
    parentObj => {
      parentObj.registerC = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD C, A
    //#0x4F:
    parentObj => {
      parentObj.registerC = parentObj.registerA;
    },
    //LD D, B
    //#0x50:
    parentObj => {
      parentObj.registerD = parentObj.registerB;
    },
    //LD D, C
    //#0x51:
    parentObj => {
      parentObj.registerD = parentObj.registerC;
    },
    //LD D, D
    //#0x52:
    parentObj => {
      //Do nothing...
    },
    //LD D, E
    //#0x53:
    parentObj => {
      parentObj.registerD = parentObj.registerE;
    },
    //LD D, H
    //#0x54:
    parentObj => {
      parentObj.registerD = parentObj.registersHL >> GBEMU_8;
    },
    //LD D, L
    //#0x55:
    parentObj => {
      parentObj.registerD = parentObj.registersHL & GBEMU_0xFF;
    },
    //LD D, (HL)
    //#0x56:
    parentObj => {
      parentObj.registerD = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD D, A
    //#0x57:
    parentObj => {
      parentObj.registerD = parentObj.registerA;
    },
    //LD E, B
    //#0x58:
    parentObj => {
      parentObj.registerE = parentObj.registerB;
    },
    //LD E, C
    //#0x59:
    parentObj => {
      parentObj.registerE = parentObj.registerC;
    },
    //LD E, D
    //#0x5A:
    parentObj => {
      parentObj.registerE = parentObj.registerD;
    },
    //LD E, E
    //#0x5B:
    parentObj => {
      //Do nothing...
    },
    //LD E, H
    //#0x5C:
    parentObj => {
      parentObj.registerE = parentObj.registersHL >> GBEMU_8;
    },
    //LD E, L
    //#0x5D:
    parentObj => {
      parentObj.registerE = parentObj.registersHL & GBEMU_0xFF;
    },
    //LD E, (HL)
    //#0x5E:
    parentObj => {
      parentObj.registerE = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD E, A
    //#0x5F:
    parentObj => {
      parentObj.registerE = parentObj.registerA;
    },
    //LD H, B
    //#0x60:
    parentObj => {
      parentObj.registersHL = (parentObj.registerB << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, C
    //#0x61:
    parentObj => {
      parentObj.registersHL = (parentObj.registerC << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, D
    //#0x62:
    parentObj => {
      parentObj.registersHL = (parentObj.registerD << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, E
    //#0x63:
    parentObj => {
      parentObj.registersHL = (parentObj.registerE << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, H
    //#0x64:
    parentObj => {
      //Do nothing...
    },
    //LD H, L
    //#0x65:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF) * GBEMU_0x101;
    },
    //LD H, (HL)
    //#0x66:
    parentObj => {
      parentObj.registersHL =
        (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD H, A
    //#0x67:
    parentObj => {
      parentObj.registersHL = (parentObj.registerA << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
    },
    //LD L, B
    //#0x68:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerB;
    },
    //LD L, C
    //#0x69:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerC;
    },
    //LD L, D
    //#0x6A:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerD;
    },
    //LD L, E
    //#0x6B:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerE;
    },
    //LD L, H
    //#0x6C:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.registersHL >> GBEMU_8);
    },
    //LD L, L
    //#0x6D:
    parentObj => {
      //Do nothing...
    },
    //LD L, (HL)
    //#0x6E:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD L, A
    //#0x6F:
    parentObj => {
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerA;
    },
    //LD (HL), B
    //#0x70:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerB);
    },
    //LD (HL), C
    //#0x71:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerC);
    },
    //LD (HL), D
    //#0x72:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerD);
    },
    //LD (HL), E
    //#0x73:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerE);
    },
    //LD (HL), H
    //#0x74:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL >> GBEMU_8);
    },
    //LD (HL), L
    //#0x75:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL & GBEMU_0xFF);
    },
    //HALT
    //#0x76:
    parentObj => {
      //See if there's already an IRQ match:
      if ((parentObj.interruptsEnabled & parentObj.interruptsRequested & GBEMU_0x1F) > 0) {
        if (!parentObj.cGBC && !parentObj.usedBootrom) {
          //HALT bug in the DMG CPU model (Program Counter fails to increment for one instruction after HALT):
          parentObj.skipPCIncrement = true;
        } else {
          //CGB gets around the HALT PC bug by doubling the hidden NOP.
          parentObj.cpuTicks += GBEMU_4;
        }
      } else {
        //CPU is stalled until the next IRQ match:
        parentObj.calculateHALTPeriod();
      }
    },
    //LD (HL), A
    //#0x77:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
    },
    //LD A, B
    //#0x78:
    parentObj => {
      parentObj.registerA = parentObj.registerB;
    },
    //LD A, C
    //#0x79:
    parentObj => {
      parentObj.registerA = parentObj.registerC;
    },
    //LD A, D
    //#0x7A:
    parentObj => {
      parentObj.registerA = parentObj.registerD;
    },
    //LD A, E
    //#0x7B:
    parentObj => {
      parentObj.registerA = parentObj.registerE;
    },
    //LD A, H
    //#0x7C:
    parentObj => {
      parentObj.registerA = parentObj.registersHL >> GBEMU_8;
    },
    //LD A, L
    //#0x7D:
    parentObj => {
      parentObj.registerA = parentObj.registersHL & GBEMU_0xFF;
    },
    //LD, A, (HL)
    //#0x7E:
    parentObj => {
      parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
    },
    //LD A, A
    //#0x7F:
    parentObj => {
      //Do Nothing...
    },
    //ADD A, B
    //#0x80:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerB;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, C
    //#0x81:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerC;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, D
    //#0x82:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerD;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, E
    //#0x83:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerE;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, H
    //#0x84:
    parentObj => {
      let dirtySum = parentObj.registerA + (parentObj.registersHL >> GBEMU_8);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, L
    //#0x85:
    parentObj => {
      let dirtySum = parentObj.registerA + (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, (HL)
    //#0x86:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADD A, A
    //#0x87:
    parentObj => {
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0x8) === GBEMU_0x8;
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = (parentObj.registerA << 1) & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, B
    //#0x88:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerB + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerB & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, C
    //#0x89:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerC + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerC & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, D
    //#0x8A:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerD + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerD & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, E
    //#0x8B:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.registerE + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerE & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, H
    //#0x8C:
    parentObj => {
      let tempValue = parentObj.registersHL >> GBEMU_8;
      let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, L
    //#0x8D:
    parentObj => {
      let tempValue = parentObj.registersHL & GBEMU_0xFF;
      let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, (HL)
    //#0x8E:
    parentObj => {
      let tempValue = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //ADC A, A
    //#0x8F:
    parentObj => {
      //shift left register A one bit for some ops here as an optimization:
      let dirtySum = (parentObj.registerA << 1) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (((parentObj.registerA << 1) & GBEMU_0x1E) | (parentObj.fCarry ? 1 : 0)) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //SUB A, B
    //#0x90:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerB;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, C
    //#0x91:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerC;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, D
    //#0x92:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerD;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, E
    //#0x93:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerE;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, H
    //#0x94:
    parentObj => {
      let dirtySum = parentObj.registerA - (parentObj.registersHL >> GBEMU_8);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, L
    //#0x95:
    parentObj => {
      let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, (HL)
    //#0x96:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //SUB A, A
    //#0x97:
    parentObj => {
      //number - same number === 0
      parentObj.registerA = 0;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
      parentObj.fZero = true;
      parentObj.fSubtract = true;
    },
    //SBC A, B
    //#0x98:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerB - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerB & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, C
    //#0x99:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerC - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerC & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, D
    //#0x9A:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerD - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerD & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, E
    //#0x9B:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerE - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerE & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, H
    //#0x9C:
    parentObj => {
      let tempVar = parentObj.registersHL >> GBEMU_8;
      let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, L
    //#0x9D:
    parentObj => {
      let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF) - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registersHL & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, (HL)
    //#0x9E:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //SBC A, A
    //#0x9F:
    parentObj => {
      //Optimized SBC A:
      if (parentObj.fCarry) {
        parentObj.fZero = false;
        parentObj.fSubtract = true;
        parentObj.fHalfCarry = true;
        parentObj.fCarry = true;
        parentObj.registerA = GBEMU_0xFF;
      } else {
        parentObj.fHalfCarry = false;
        parentObj.fCarry = false;
        parentObj.fSubtract = true;
        parentObj.fZero = true;
        parentObj.registerA = 0;
      }
    },
    //AND B
    //#0xA0:
    parentObj => {
      parentObj.registerA &= parentObj.registerB;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND C
    //#0xA1:
    parentObj => {
      parentObj.registerA &= parentObj.registerC;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND D
    //#0xA2:
    parentObj => {
      parentObj.registerA &= parentObj.registerD;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND E
    //#0xA3:
    parentObj => {
      parentObj.registerA &= parentObj.registerE;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND H
    //#0xA4:
    parentObj => {
      parentObj.registerA &= parentObj.registersHL >> GBEMU_8;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND L
    //#0xA5:
    parentObj => {
      parentObj.registerA &= parentObj.registersHL;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND (HL)
    //#0xA6:
    parentObj => {
      parentObj.registerA &= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //AND A
    //#0xA7:
    parentObj => {
      //number & same number = same number
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //XOR B
    //#0xA8:
    parentObj => {
      parentObj.registerA ^= parentObj.registerB;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR C
    //#0xA9:
    parentObj => {
      parentObj.registerA ^= parentObj.registerC;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR D
    //#0xAA:
    parentObj => {
      parentObj.registerA ^= parentObj.registerD;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR E
    //#0xAB:
    parentObj => {
      parentObj.registerA ^= parentObj.registerE;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR H
    //#0xAC:
    parentObj => {
      parentObj.registerA ^= parentObj.registersHL >> GBEMU_8;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR L
    //#0xAD:
    parentObj => {
      parentObj.registerA ^= parentObj.registersHL & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR (HL)
    //#0xAE:
    parentObj => {
      parentObj.registerA ^= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //XOR A
    //#0xAF:
    parentObj => {
      //number ^ same number === 0
      parentObj.registerA = 0;
      parentObj.fZero = true;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //OR B
    //#0xB0:
    parentObj => {
      parentObj.registerA |= parentObj.registerB;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR C
    //#0xB1:
    parentObj => {
      parentObj.registerA |= parentObj.registerC;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR D
    //#0xB2:
    parentObj => {
      parentObj.registerA |= parentObj.registerD;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR E
    //#0xB3:
    parentObj => {
      parentObj.registerA |= parentObj.registerE;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR H
    //#0xB4:
    parentObj => {
      parentObj.registerA |= parentObj.registersHL >> GBEMU_8;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR L
    //#0xB5:
    parentObj => {
      parentObj.registerA |= parentObj.registersHL & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR (HL)
    //#0xB6:
    parentObj => {
      parentObj.registerA |= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //OR A
    //#0xB7:
    parentObj => {
      //number | same number === same number
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //CP B
    //#0xB8:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerB;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP C
    //#0xB9:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerC;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP D
    //#0xBA:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerD;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP E
    //#0xBB:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.registerE;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP H
    //#0xBC:
    parentObj => {
      let dirtySum = parentObj.registerA - (parentObj.registersHL >> GBEMU_8);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP L
    //#0xBD:
    parentObj => {
      let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP (HL)
    //#0xBE:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //CP A
    //#0xBF:
    parentObj => {
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
      parentObj.fZero = true;
      parentObj.fSubtract = true;
    },
    //RET !FZ
    //#0xC0:
    parentObj => {
      if (!parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
        parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_12;
      }
    },
    //POP BC
    //#0xC1:
    parentObj => {
      parentObj.registerC = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.registerB = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
    },
    //JP !FZ, nn
    //#0xC2:
    parentObj => {
      if (!parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //JP nn
    //#0xC3:
    parentObj => {
      parentObj.programCounter =
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
    },
    //CALL !FZ, nn
    //#0xC4:
    parentObj => {
      if (!parentObj.fZero) {
        let temp_pc =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
        parentObj.programCounter = temp_pc;
        parentObj.cpuTicks += GBEMU_12;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //PUSH BC
    //#0xC5:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerB);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerC);
    },
    //ADD, n
    //#0xC6:
    parentObj => {
      let dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //RST 0
    //#0xC7:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = 0;
    },
    //RET FZ
    //#0xC8:
    parentObj => {
      if (parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
        parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_12;
      }
    },
    //RET
    //#0xC9:
    parentObj => {
      parentObj.programCounter =
        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
    },
    //JP FZ, nn
    //#0xCA:
    parentObj => {
      if (parentObj.fZero) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //Secondary OP Code Set:
    //#0xCB:
    parentObj => {
      let opcode = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      //Increment the program counter to the next instruction:
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      //Execute secondary OP codes for the 0xCB OP code call.
      parentObj.cbOpCode[opcode](parentObj);
      //Get how many CPU cycles the current 0xCBXX op code counts for:
      parentObj.cpuTicks += parentObj.secondaryTickTable[opcode];
    },
    //CALL FZ, nn
    //#0xCC:
    parentObj => {
      if (parentObj.fZero) {
        let temp_pc =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
        parentObj.programCounter = temp_pc;
        parentObj.cpuTicks += GBEMU_12;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //CALL nn
    //#0xCD:
    parentObj => {
      let temp_pc =
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = temp_pc;
    },
    //ADC A, n
    //#0xCE:
    parentObj => {
      let tempValue = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
      parentObj.fCarry = dirtySum > GBEMU_0xFF;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
    },
    //RST 0x8
    //#0xCF:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = 0x8;
    },
    //RET !FC
    //#0xD0:
    parentObj => {
      if (!parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
        parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_12;
      }
    },
    //POP DE
    //#0xD1:
    parentObj => {
      parentObj.registerE = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.registerD = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
    },
    //JP !FC, nn
    //#0xD2:
    parentObj => {
      if (!parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //0xD3 - Illegal
    //#0xD3:
    parentObj => {
      cout('Illegal op code 0xD3 called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //CALL !FC, nn
    //#0xD4:
    parentObj => {
      if (!parentObj.fCarry) {
        let tempPc =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
        parentObj.programCounter = tempPc;
        parentObj.cpuTicks += GBEMU_12;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //PUSH DE
    //#0xD5:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerD);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerE);
    },
    //SUB A, n
    //#0xD6:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //RST 0x10
    //#0xD7:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x10;
    },
    //RET FC
    //#0xD8:
    parentObj => {
      if (parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
        parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.cpuTicks += GBEMU_12;
      }
    },
    //RETI
    //#0xD9:
    parentObj => {
      parentObj.programCounter =
        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
      //Immediate for HALT:
      parentObj.irqEnableDelay =
        parentObj.irqEnableDelay === GBEMU_2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) === GBEMU_0x76 ?
          1 :
          GBEMU_2;
    },
    //JP FC, nn
    //#0xDA:
    parentObj => {
      if (parentObj.fCarry) {
        parentObj.programCounter =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.cpuTicks += GBEMU_4;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //0xDB - Illegal
    //#0xDB:
    parentObj => {
      cout('Illegal op code 0xDB called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //CALL FC, nn
    //#0xDC:
    parentObj => {
      if (parentObj.fCarry) {
        let tempPc =
          (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
        parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
        parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
        parentObj.programCounter = tempPc;
        parentObj.cpuTicks += GBEMU_12;
      } else {
        parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
      }
    },
    //0xDD - Illegal
    //#0xDD:
    parentObj => {
      cout('Illegal op code 0xDD called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //SBC A, n
    //#0xDE:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
      parentObj.fCarry = dirtySum < 0;
      parentObj.registerA = dirtySum & GBEMU_0xFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = true;
    },
    //RST 0x18
    //#0xDF:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x18;
    },
    //LDH (n), A
    //#0xE0:
    parentObj => {
      parentObj.memoryHighWrite(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //POP HL
    //#0xE1:
    parentObj => {
      parentObj.registersHL =
        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LD (0xFF00 + C), A
    //#0xE2:
    parentObj => {
      parentObj.memoryHighWriter[parentObj.registerC](parentObj, parentObj.registerC, parentObj.registerA);
    },
    //0xE3 - Illegal
    //#0xE3:
    parentObj => {
      cout('Illegal op code 0xE3 called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //0xE4 - Illegal
    //#0xE4:
    parentObj => {
      cout('Illegal op code 0xE4 called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //PUSH HL
    //#0xE5:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL & GBEMU_0xFF);
    },
    //AND n
    //#0xE6:
    parentObj => {
      parentObj.registerA &= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
    },
    //RST 0x20
    //#0xE7:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x20;
    },
    //ADD SP, n
    //#0xE8:
    parentObj => {
      let tempValue2 = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24;
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      let tempValue = (parentObj.stackPointer + tempValue2) & GBEMU_0xFFFF;
      tempValue2 = parentObj.stackPointer ^ tempValue2 ^ tempValue;
      parentObj.stackPointer = tempValue;
      parentObj.fCarry = (tempValue2 & GBEMU_0x100) === GBEMU_0x100;
      parentObj.fHalfCarry = (tempValue2 & GBEMU_0x10) === GBEMU_0x10;
      parentObj.fZero = false;
      parentObj.fSubtract = false;
    },
    //JP, (HL)
    //#0xE9:
    parentObj => {
      parentObj.programCounter = parentObj.registersHL;
    },
    //LD n, A
    //#0xEA:
    parentObj => {
      parentObj.memoryWrite(
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter),
        parentObj.registerA
      );
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //0xEB - Illegal
    //#0xEB:
    parentObj => {
      cout('Illegal op code 0xEB called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //0xEC - Illegal
    //#0xEC:
    parentObj => {
      cout('Illegal op code 0xEC called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //0xED - Illegal
    //#0xED:
    parentObj => {
      cout('Illegal op code 0xED called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //XOR n
    //#0xEE:
    parentObj => {
      parentObj.registerA ^= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fSubtract = false;
      parentObj.fHalfCarry = false;
      parentObj.fCarry = false;
    },
    //RST 0x28
    //#0xEF:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x28;
    },
    //LDH A, (n)
    //#0xF0:
    parentObj => {
      parentObj.registerA = parentObj.memoryHighRead(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
    },
    //POP AF
    //#0xF1:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
      parentObj.fZero = tempVar > GBEMU_0x7F;
      parentObj.fSubtract = (tempVar & GBEMU_0x40) === GBEMU_0x40;
      parentObj.fHalfCarry = (tempVar & GBEMU_0x20) === GBEMU_0x20;
      parentObj.fCarry = (tempVar & GBEMU_0x10) === GBEMU_0x10;
      parentObj.registerA = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
      parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
    },
    //LD A, (0xFF00 + C)
    //#0xF2:
    parentObj => {
      parentObj.registerA = parentObj.memoryHighReader[parentObj.registerC](parentObj, parentObj.registerC);
    },
    //DI
    //#0xF3:
    parentObj => {
      parentObj.ime = false;
      parentObj.irqEnableDelay = 0;
    },
    //0xF4 - Illegal
    //#0xF4:
    parentObj => {
      cout('Illegal op code 0xF4 called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //PUSH AF
    //#0xF5:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerA);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](
        parentObj,
        parentObj.stackPointer,
        (parentObj.fZero ? GBEMU_0x80 : 0) |
          (parentObj.fSubtract ? GBEMU_0x40 : 0) |
          (parentObj.fHalfCarry ? GBEMU_0x20 : 0) |
          (parentObj.fCarry ? GBEMU_0x10 : 0)
      );
    },
    //OR n
    //#0xF6:
    parentObj => {
      parentObj.registerA |= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fSubtract = false;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
    },
    //RST 0x30
    //#0xF7:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x30;
    },
    //LDHL SP, n
    //#0xF8:
    parentObj => {
      let tempVar = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24;
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.registersHL = (parentObj.stackPointer + tempVar) & GBEMU_0xFFFF;
      tempVar = parentObj.stackPointer ^ tempVar ^ parentObj.registersHL;
      parentObj.fCarry = (tempVar & GBEMU_0x100) === GBEMU_0x100;
      parentObj.fHalfCarry = (tempVar & GBEMU_0x10) === GBEMU_0x10;
      parentObj.fZero = false;
      parentObj.fSubtract = false;
    },
    //LD SP, HL
    //#0xF9:
    parentObj => {
      parentObj.stackPointer = parentObj.registersHL;
    },
    //LD A, (nn)
    //#0xFA:
    parentObj => {
      parentObj.registerA = parentObj.memoryRead(
        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
          parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter)
      );
      parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
    },
    //EI
    //#0xFB:
    parentObj => {
      //Immediate for HALT:
      parentObj.irqEnableDelay =
        parentObj.irqEnableDelay === GBEMU_2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) === GBEMU_0x76 ?
          1 :
          GBEMU_2;
    },
    //0xFC - Illegal
    //#0xFC:
    parentObj => {
      cout('Illegal op code 0xFC called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //0xFD - Illegal
    //#0xFD:
    parentObj => {
      cout('Illegal op code 0xFD called, pausing emulation.', GBEMU_2);
      pausePlay();
    },
    //CP n
    //#0xFE:
    parentObj => {
      let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
      parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
      parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
      parentObj.fCarry = dirtySum < 0;
      parentObj.fZero = dirtySum === 0;
      parentObj.fSubtract = true;
    },
    //RST 0x38
    //#0xFF:
    parentObj => {
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
      parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
      parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
      parentObj.programCounter = GBEMU_0x38;
    }
  ];
  cbOpCode: Array<(parentObj: GameBoyCore) => void> = [
    //RLC B
    //#0x00:
    parentObj => {
      parentObj.fCarry = parentObj.registerB > GBEMU_0x7F;
      parentObj.registerB = ((parentObj.registerB << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //RLC C
    //#0x01:
    parentObj => {
      parentObj.fCarry = parentObj.registerC > GBEMU_0x7F;
      parentObj.registerC = ((parentObj.registerC << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //RLC D
    //#0x02:
    parentObj => {
      parentObj.fCarry = parentObj.registerD > GBEMU_0x7F;
      parentObj.registerD = ((parentObj.registerD << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //RLC E
    //#0x03:
    parentObj => {
      parentObj.fCarry = parentObj.registerE > GBEMU_0x7F;
      parentObj.registerE = ((parentObj.registerE << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //RLC H
    //#0x04:
    parentObj => {
      parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
      parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.fCarry ? GBEMU_0x100 : 0) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //RLC L
    //#0x05:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x80) === GBEMU_0x80;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //RLC (HL)
    //#0x06:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fCarry = tempVar > GBEMU_0x7F;
      tempVar = ((tempVar << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //RLC A
    //#0x07:
    parentObj => {
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //RRC B
    //#0x08:
    parentObj => {
      parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerB = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerB >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //RRC C
    //#0x09:
    parentObj => {
      parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerC = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerC >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //RRC D
    //#0x0A:
    parentObj => {
      parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerD = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerD >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //RRC E
    //#0x0B:
    parentObj => {
      parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerE = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerE >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //RRC H
    //#0x0C:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
      parentObj.registersHL = (parentObj.fCarry ? GBEMU_0x8000 : 0) | ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //RRC L
    //#0x0D:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.fCarry ? GBEMU_0x80 : 0) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //RRC (HL)
    //#0x0E:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
      tempVar = (parentObj.fCarry ? GBEMU_0x80 : 0) | (tempVar >> 1);
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //RRC A
    //#0x0F:
    parentObj => {
      parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerA = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerA >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //RL B
    //#0x10:
    parentObj => {
      let newfCarry = parentObj.registerB > GBEMU_0x7F;
      parentObj.registerB = ((parentObj.registerB << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //RL C
    //#0x11:
    parentObj => {
      let newfCarry = parentObj.registerC > GBEMU_0x7F;
      parentObj.registerC = ((parentObj.registerC << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //RL D
    //#0x12:
    parentObj => {
      let newfCarry = parentObj.registerD > GBEMU_0x7F;
      parentObj.registerD = ((parentObj.registerD << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //RL E
    //#0x13:
    parentObj => {
      let newfCarry = parentObj.registerE > GBEMU_0x7F;
      parentObj.registerE = ((parentObj.registerE << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //RL H
    //#0x14:
    parentObj => {
      let newfCarry = parentObj.registersHL > GBEMU_0x7FFF;
      parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.fCarry ? GBEMU_0x100 : 0) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //RL L
    //#0x15:
    parentObj => {
      let newfCarry = (parentObj.registersHL & GBEMU_0x80) === GBEMU_0x80;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //RL (HL)
    //#0x16:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      let newfCarry = tempVar > GBEMU_0x7F;
      tempVar = ((tempVar << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //RL A
    //#0x17:
    parentObj => {
      let newfCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //RR B
    //#0x18:
    parentObj => {
      let newfCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerB = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerB >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //RR C
    //#0x19:
    parentObj => {
      let newfCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerC = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerC >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //RR D
    //#0x1A:
    parentObj => {
      let newfCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerD = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerD >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //RR E
    //#0x1B:
    parentObj => {
      let newfCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerE = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerE >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //RR H
    //#0x1C:
    parentObj => {
      let newfCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
      parentObj.registersHL = (parentObj.fCarry ? GBEMU_0x8000 : 0) | ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //RR L
    //#0x1D:
    parentObj => {
      let newfCarry = (parentObj.registersHL & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.fCarry ? GBEMU_0x80 : 0) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //RR (HL)
    //#0x1E:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      let newfCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
      tempVar = (parentObj.fCarry ? GBEMU_0x80 : 0) | (tempVar >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //RR A
    //#0x1F:
    parentObj => {
      let newfCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerA = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerA >> 1);
      parentObj.fCarry = newfCarry;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //SLA B
    //#0x20:
    parentObj => {
      parentObj.fCarry = parentObj.registerB > GBEMU_0x7F;
      parentObj.registerB = (parentObj.registerB << 1) & GBEMU_0xFF;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //SLA C
    //#0x21:
    parentObj => {
      parentObj.fCarry = parentObj.registerC > GBEMU_0x7F;
      parentObj.registerC = (parentObj.registerC << 1) & GBEMU_0xFF;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //SLA D
    //#0x22:
    parentObj => {
      parentObj.fCarry = parentObj.registerD > GBEMU_0x7F;
      parentObj.registerD = (parentObj.registerD << 1) & GBEMU_0xFF;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //SLA E
    //#0x23:
    parentObj => {
      parentObj.fCarry = parentObj.registerE > GBEMU_0x7F;
      parentObj.registerE = (parentObj.registerE << 1) & GBEMU_0xFF;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //SLA H
    //#0x24:
    parentObj => {
      parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
      parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //SLA L
    //#0x25:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0080) === GBEMU_0x0080;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //SLA (HL)
    //#0x26:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fCarry = tempVar > GBEMU_0x7F;
      tempVar = (tempVar << 1) & GBEMU_0xFF;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //SLA A
    //#0x27:
    parentObj => {
      parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
      parentObj.registerA = (parentObj.registerA << 1) & GBEMU_0xFF;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //SRA B
    //#0x28:
    parentObj => {
      parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerB = (parentObj.registerB & GBEMU_0x80) | (parentObj.registerB >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //SRA C
    //#0x29:
    parentObj => {
      parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerC = (parentObj.registerC & GBEMU_0x80) | (parentObj.registerC >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //SRA D
    //#0x2A:
    parentObj => {
      parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerD = (parentObj.registerD & GBEMU_0x80) | (parentObj.registerD >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //SRA E
    //#0x2B:
    parentObj => {
      parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerE = (parentObj.registerE & GBEMU_0x80) | (parentObj.registerE >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //SRA H
    //#0x2C:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
      parentObj.registersHL = ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0x80FF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //SRA L
    //#0x2D:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0001) === GBEMU_0x0001;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF80) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //SRA (HL)
    //#0x2E:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
      tempVar = (tempVar & GBEMU_0x80) | (tempVar >> 1);
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar === 0;
    },
    //SRA A
    //#0x2F:
    parentObj => {
      parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerA = (parentObj.registerA & GBEMU_0x80) | (parentObj.registerA >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //SWAP B
    //#0x30:
    parentObj => {
      parentObj.registerB = ((parentObj.registerB & GBEMU_0xF) << GBEMU_4) | (parentObj.registerB >> GBEMU_4);
      parentObj.fZero = parentObj.registerB === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP C
    //#0x31:
    parentObj => {
      parentObj.registerC = ((parentObj.registerC & GBEMU_0xF) << GBEMU_4) | (parentObj.registerC >> GBEMU_4);
      parentObj.fZero = parentObj.registerC === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP D
    //#0x32:
    parentObj => {
      parentObj.registerD = ((parentObj.registerD & GBEMU_0xF) << GBEMU_4) | (parentObj.registerD >> GBEMU_4);
      parentObj.fZero = parentObj.registerD === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP E
    //#0x33:
    parentObj => {
      parentObj.registerE = ((parentObj.registerE & GBEMU_0xF) << GBEMU_4) | (parentObj.registerE >> GBEMU_4);
      parentObj.fZero = parentObj.registerE === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP H
    //#0x34:
    parentObj => {
      parentObj.registersHL =
        ((parentObj.registersHL & GBEMU_0xF00) << GBEMU_4) | ((parentObj.registersHL & GBEMU_0xF000) >> GBEMU_4) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP L
    //#0x35:
    parentObj => {
      parentObj.registersHL =
        (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL & GBEMU_0xF) << GBEMU_4) | ((parentObj.registersHL & GBEMU_0xF0) >> GBEMU_4);
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP (HL)
    //#0x36:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      tempVar = ((tempVar & GBEMU_0xF) << GBEMU_4) | (tempVar >> GBEMU_4);
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
      parentObj.fZero = tempVar === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SWAP A
    //#0x37:
    parentObj => {
      parentObj.registerA = ((parentObj.registerA & GBEMU_0xF) << GBEMU_4) | (parentObj.registerA >> GBEMU_4);
      parentObj.fZero = parentObj.registerA === 0;
      parentObj.fCarry = false;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
    },
    //SRL B
    //#0x38:
    parentObj => {
      parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerB >>= 1;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerB === 0;
    },
    //SRL C
    //#0x39:
    parentObj => {
      parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerC >>= 1;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerC === 0;
    },
    //SRL D
    //#0x3A:
    parentObj => {
      parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerD >>= 1;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerD === 0;
    },
    //SRL E
    //#0x3B:
    parentObj => {
      parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerE >>= 1;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerE === 0;
    },
    //SRL H
    //#0x3C:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
      parentObj.registersHL = ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
    },
    //SRL L
    //#0x3D:
    parentObj => {
      parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0001) === GBEMU_0x0001;
      parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
    },
    //SRL (HL)
    //#0x3E:
    parentObj => {
      let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
      parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
      parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar >> 1);
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = tempVar < GBEMU_2;
    },
    //SRL A
    //#0x3F:
    parentObj => {
      parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
      parentObj.registerA >>= 1;
      parentObj.fHalfCarry = false;
      parentObj.fSubtract = false;
      parentObj.fZero = parentObj.registerA === 0;
    },
    //BIT 0, B
    //#0x40:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x01) === 0;
    },
    //BIT 0, C
    //#0x41:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x01) === 0;
    },
    //BIT 0, D
    //#0x42:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x01) === 0;
    },
    //BIT 0, E
    //#0x43:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x01) === 0;
    },
    //BIT 0, H
    //#0x44:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0100) === 0;
    },
    //BIT 0, L
    //#0x45:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0001) === 0;
    },
    //BIT 0, (HL)
    //#0x46:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x01) === 0;
    },
    //BIT 0, A
    //#0x47:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x01) === 0;
    },
    //BIT 1, B
    //#0x48:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x02) === 0;
    },
    //BIT 1, C
    //#0x49:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x02) === 0;
    },
    //BIT 1, D
    //#0x4A:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x02) === 0;
    },
    //BIT 1, E
    //#0x4B:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x02) === 0;
    },
    //BIT 1, H
    //#0x4C:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0200) === 0;
    },
    //BIT 1, L
    //#0x4D:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0002) === 0;
    },
    //BIT 1, (HL)
    //#0x4E:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x02) === 0;
    },
    //BIT 1, A
    //#0x4F:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x02) === 0;
    },
    //BIT GBEMU_2, B
    //#0x50:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_2, C
    //#0x51:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_2, D
    //#0x52:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_2, E
    //#0x53:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_2, H
    //#0x54:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0400) === 0;
    },
    //BIT GBEMU_2, L
    //#0x55:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0004) === 0;
    },
    //BIT GBEMU_2, (HL)
    //#0x56:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_2, A
    //#0x57:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x04) === 0;
    },
    //BIT GBEMU_3, B
    //#0x58:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_3, C
    //#0x59:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_3, D
    //#0x5A:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_3, E
    //#0x5B:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_3, H
    //#0x5C:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0800) === 0;
    },
    //BIT GBEMU_3, L
    //#0x5D:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0008) === 0;
    },
    //BIT GBEMU_3, (HL)
    //#0x5E:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_3, A
    //#0x5F:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x08) === 0;
    },
    //BIT GBEMU_4, B
    //#0x60:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_4, C
    //#0x61:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_4, D
    //#0x62:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_4, E
    //#0x63:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_4, H
    //#0x64:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x1000) === 0;
    },
    //BIT GBEMU_4, L
    //#0x65:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0010) === 0;
    },
    //BIT GBEMU_4, (HL)
    //#0x66:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_4, A
    //#0x67:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x10) === 0;
    },
    //BIT GBEMU_5, B
    //#0x68:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_5, C
    //#0x69:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_5, D
    //#0x6A:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_5, E
    //#0x6B:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_5, H
    //#0x6C:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x2000) === 0;
    },
    //BIT GBEMU_5, L
    //#0x6D:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0020) === 0;
    },
    //BIT GBEMU_5, (HL)
    //#0x6E:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_5, A
    //#0x6F:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x20) === 0;
    },
    //BIT GBEMU_6, B
    //#0x70:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_6, C
    //#0x71:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_6, D
    //#0x72:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_6, E
    //#0x73:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_6, H
    //#0x74:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x4000) === 0;
    },
    //BIT GBEMU_6, L
    //#0x75:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0040) === 0;
    },
    //BIT GBEMU_6, (HL)
    //#0x76:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_6, A
    //#0x77:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x40) === 0;
    },
    //BIT GBEMU_7, B
    //#0x78:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerB & GBEMU_0x80) === 0;
    },
    //BIT GBEMU_7, C
    //#0x79:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerC & GBEMU_0x80) === 0;
    },
    //BIT GBEMU_7, D
    //#0x7A:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerD & GBEMU_0x80) === 0;
    },
    //BIT GBEMU_7, E
    //#0x7B:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerE & GBEMU_0x80) === 0;
    },
    //BIT GBEMU_7, H
    //#0x7C:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x8000) === 0;
    },
    //BIT GBEMU_7, L
    //#0x7D:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registersHL & GBEMU_0x0080) === 0;
    },
    //BIT GBEMU_7, (HL)
    //#0x7E:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x80) === 0;
    },
    //BIT GBEMU_7, A
    //#0x7F:
    parentObj => {
      parentObj.fHalfCarry = true;
      parentObj.fSubtract = false;
      parentObj.fZero = (parentObj.registerA & GBEMU_0x80) === 0;
    },
    //RES 0, B
    //#0x80:
    parentObj => {
      parentObj.registerB &= GBEMU_0xFE;
    },
    //RES 0, C
    //#0x81:
    parentObj => {
      parentObj.registerC &= GBEMU_0xFE;
    },
    //RES 0, D
    //#0x82:
    parentObj => {
      parentObj.registerD &= GBEMU_0xFE;
    },
    //RES 0, E
    //#0x83:
    parentObj => {
      parentObj.registerE &= GBEMU_0xFE;
    },
    //RES 0, H
    //#0x84:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFEFF;
    },
    //RES 0, L
    //#0x85:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFFE;
    },
    //RES 0, (HL)
    //#0x86:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFE
      );
    },
    //RES 0, A
    //#0x87:
    parentObj => {
      parentObj.registerA &= GBEMU_0xFE;
    },
    //RES 1, B
    //#0x88:
    parentObj => {
      parentObj.registerB &= GBEMU_0xFD;
    },
    //RES 1, C
    //#0x89:
    parentObj => {
      parentObj.registerC &= GBEMU_0xFD;
    },
    //RES 1, D
    //#0x8A:
    parentObj => {
      parentObj.registerD &= GBEMU_0xFD;
    },
    //RES 1, E
    //#0x8B:
    parentObj => {
      parentObj.registerE &= GBEMU_0xFD;
    },
    //RES 1, H
    //#0x8C:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFDFF;
    },
    //RES 1, L
    //#0x8D:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFFD;
    },
    //RES 1, (HL)
    //#0x8E:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFD
      );
    },
    //RES 1, A
    //#0x8F:
    parentObj => {
      parentObj.registerA &= GBEMU_0xFD;
    },
    //RES GBEMU_2, B
    //#0x90:
    parentObj => {
      parentObj.registerB &= GBEMU_0xFB;
    },
    //RES GBEMU_2, C
    //#0x91:
    parentObj => {
      parentObj.registerC &= GBEMU_0xFB;
    },
    //RES GBEMU_2, D
    //#0x92:
    parentObj => {
      parentObj.registerD &= GBEMU_0xFB;
    },
    //RES GBEMU_2, E
    //#0x93:
    parentObj => {
      parentObj.registerE &= GBEMU_0xFB;
    },
    //RES GBEMU_2, H
    //#0x94:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFBFF;
    },
    //RES GBEMU_2, L
    //#0x95:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFFB;
    },
    //RES GBEMU_2, (HL)
    //#0x96:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFB
      );
    },
    //RES GBEMU_2, A
    //#0x97:
    parentObj => {
      parentObj.registerA &= GBEMU_0xFB;
    },
    //RES GBEMU_3, B
    //#0x98:
    parentObj => {
      parentObj.registerB &= GBEMU_0xF7;
    },
    //RES GBEMU_3, C
    //#0x99:
    parentObj => {
      parentObj.registerC &= GBEMU_0xF7;
    },
    //RES GBEMU_3, D
    //#0x9A:
    parentObj => {
      parentObj.registerD &= GBEMU_0xF7;
    },
    //RES GBEMU_3, E
    //#0x9B:
    parentObj => {
      parentObj.registerE &= GBEMU_0xF7;
    },
    //RES GBEMU_3, H
    //#0x9C:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xF7FF;
    },
    //RES GBEMU_3, L
    //#0x9D:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFF7;
    },
    //RES GBEMU_3, (HL)
    //#0x9E:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xF7
      );
    },
    //RES GBEMU_3, A
    //#0x9F:
    parentObj => {
      parentObj.registerA &= GBEMU_0xF7;
    },
    //RES GBEMU_3, B
    //#0xA0:
    parentObj => {
      parentObj.registerB &= GBEMU_0xEF;
    },
    //RES GBEMU_4, C
    //#0xA1:
    parentObj => {
      parentObj.registerC &= GBEMU_0xEF;
    },
    //RES GBEMU_4, D
    //#0xA2:
    parentObj => {
      parentObj.registerD &= GBEMU_0xEF;
    },
    //RES GBEMU_4, E
    //#0xA3:
    parentObj => {
      parentObj.registerE &= GBEMU_0xEF;
    },
    //RES GBEMU_4, H
    //#0xA4:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xEFFF;
    },
    //RES GBEMU_4, L
    //#0xA5:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFEF;
    },
    //RES GBEMU_4, (HL)
    //#0xA6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xEF
      );
    },
    //RES GBEMU_4, A
    //#0xA7:
    parentObj => {
      parentObj.registerA &= GBEMU_0xEF;
    },
    //RES GBEMU_5, B
    //#0xA8:
    parentObj => {
      parentObj.registerB &= GBEMU_0xDF;
    },
    //RES GBEMU_5, C
    //#0xA9:
    parentObj => {
      parentObj.registerC &= GBEMU_0xDF;
    },
    //RES GBEMU_5, D
    //#0xAA:
    parentObj => {
      parentObj.registerD &= GBEMU_0xDF;
    },
    //RES GBEMU_5, E
    //#0xAB:
    parentObj => {
      parentObj.registerE &= GBEMU_0xDF;
    },
    //RES GBEMU_5, H
    //#0xAC:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xDFFF;
    },
    //RES GBEMU_5, L
    //#0xAD:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFDF;
    },
    //RES GBEMU_5, (HL)
    //#0xAE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xDF
      );
    },
    //RES GBEMU_5, A
    //#0xAF:
    parentObj => {
      parentObj.registerA &= GBEMU_0xDF;
    },
    //RES GBEMU_6, B
    //#0xB0:
    parentObj => {
      parentObj.registerB &= GBEMU_0xBF;
    },
    //RES GBEMU_6, C
    //#0xB1:
    parentObj => {
      parentObj.registerC &= GBEMU_0xBF;
    },
    //RES GBEMU_6, D
    //#0xB2:
    parentObj => {
      parentObj.registerD &= GBEMU_0xBF;
    },
    //RES GBEMU_6, E
    //#0xB3:
    parentObj => {
      parentObj.registerE &= GBEMU_0xBF;
    },
    //RES GBEMU_6, H
    //#0xB4:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xBFFF;
    },
    //RES GBEMU_6, L
    //#0xB5:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFFBF;
    },
    //RES GBEMU_6, (HL)
    //#0xB6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xBF
      );
    },
    //RES GBEMU_6, A
    //#0xB7:
    parentObj => {
      parentObj.registerA &= GBEMU_0xBF;
    },
    //RES GBEMU_7, B
    //#0xB8:
    parentObj => {
      parentObj.registerB &= GBEMU_0x7F;
    },
    //RES GBEMU_7, C
    //#0xB9:
    parentObj => {
      parentObj.registerC &= GBEMU_0x7F;
    },
    //RES GBEMU_7, D
    //#0xBA:
    parentObj => {
      parentObj.registerD &= GBEMU_0x7F;
    },
    //RES GBEMU_7, E
    //#0xBB:
    parentObj => {
      parentObj.registerE &= GBEMU_0x7F;
    },
    //RES GBEMU_7, H
    //#0xBC:
    parentObj => {
      parentObj.registersHL &= GBEMU_0x7FFF;
    },
    //RES GBEMU_7, L
    //#0xBD:
    parentObj => {
      parentObj.registersHL &= GBEMU_0xFF7F;
    },
    //RES GBEMU_7, (HL)
    //#0xBE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x7F
      );
    },
    //RES GBEMU_7, A
    //#0xBF:
    parentObj => {
      parentObj.registerA &= GBEMU_0x7F;
    },
    //SET 0, B
    //#0xC0:
    parentObj => {
      parentObj.registerB |= GBEMU_0x01;
    },
    //SET 0, C
    //#0xC1:
    parentObj => {
      parentObj.registerC |= GBEMU_0x01;
    },
    //SET 0, D
    //#0xC2:
    parentObj => {
      parentObj.registerD |= GBEMU_0x01;
    },
    //SET 0, E
    //#0xC3:
    parentObj => {
      parentObj.registerE |= GBEMU_0x01;
    },
    //SET 0, H
    //#0xC4:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x0100;
    },
    //SET 0, L
    //#0xC5:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x01;
    },
    //SET 0, (HL)
    //#0xC6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x01
      );
    },
    //SET 0, A
    //#0xC7:
    parentObj => {
      parentObj.registerA |= GBEMU_0x01;
    },
    //SET 1, B
    //#0xC8:
    parentObj => {
      parentObj.registerB |= GBEMU_0x02;
    },
    //SET 1, C
    //#0xC9:
    parentObj => {
      parentObj.registerC |= GBEMU_0x02;
    },
    //SET 1, D
    //#0xCA:
    parentObj => {
      parentObj.registerD |= GBEMU_0x02;
    },
    //SET 1, E
    //#0xCB:
    parentObj => {
      parentObj.registerE |= GBEMU_0x02;
    },
    //SET 1, H
    //#0xCC:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x0200;
    },
    //SET 1, L
    //#0xCD:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x02;
    },
    //SET 1, (HL)
    //#0xCE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x02
      );
    },
    //SET 1, A
    //#0xCF:
    parentObj => {
      parentObj.registerA |= GBEMU_0x02;
    },
    //SET GBEMU_2, B
    //#0xD0:
    parentObj => {
      parentObj.registerB |= GBEMU_0x04;
    },
    //SET GBEMU_2, C
    //#0xD1:
    parentObj => {
      parentObj.registerC |= GBEMU_0x04;
    },
    //SET GBEMU_2, D
    //#0xD2:
    parentObj => {
      parentObj.registerD |= GBEMU_0x04;
    },
    //SET GBEMU_2, E
    //#0xD3:
    parentObj => {
      parentObj.registerE |= GBEMU_0x04;
    },
    //SET GBEMU_2, H
    //#0xD4:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x0400;
    },
    //SET GBEMU_2, L
    //#0xD5:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x04;
    },
    //SET GBEMU_2, (HL)
    //#0xD6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x04
      );
    },
    //SET GBEMU_2, A
    //#0xD7:
    parentObj => {
      parentObj.registerA |= GBEMU_0x04;
    },
    //SET GBEMU_3, B
    //#0xD8:
    parentObj => {
      parentObj.registerB |= GBEMU_0x08;
    },
    //SET GBEMU_3, C
    //#0xD9:
    parentObj => {
      parentObj.registerC |= GBEMU_0x08;
    },
    //SET GBEMU_3, D
    //#0xDA:
    parentObj => {
      parentObj.registerD |= GBEMU_0x08;
    },
    //SET GBEMU_3, E
    //#0xDB:
    parentObj => {
      parentObj.registerE |= GBEMU_0x08;
    },
    //SET GBEMU_3, H
    //#0xDC:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x0800;
    },
    //SET GBEMU_3, L
    //#0xDD:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x08;
    },
    //SET GBEMU_3, (HL)
    //#0xDE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x08
      );
    },
    //SET GBEMU_3, A
    //#0xDF:
    parentObj => {
      parentObj.registerA |= GBEMU_0x08;
    },
    //SET GBEMU_4, B
    //#0xE0:
    parentObj => {
      parentObj.registerB |= GBEMU_0x10;
    },
    //SET GBEMU_4, C
    //#0xE1:
    parentObj => {
      parentObj.registerC |= GBEMU_0x10;
    },
    //SET GBEMU_4, D
    //#0xE2:
    parentObj => {
      parentObj.registerD |= GBEMU_0x10;
    },
    //SET GBEMU_4, E
    //#0xE3:
    parentObj => {
      parentObj.registerE |= GBEMU_0x10;
    },
    //SET GBEMU_4, H
    //#0xE4:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x1000;
    },
    //SET GBEMU_4, L
    //#0xE5:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x10;
    },
    //SET GBEMU_4, (HL)
    //#0xE6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x10
      );
    },
    //SET GBEMU_4, A
    //#0xE7:
    parentObj => {
      parentObj.registerA |= GBEMU_0x10;
    },
    //SET GBEMU_5, B
    //#0xE8:
    parentObj => {
      parentObj.registerB |= GBEMU_0x20;
    },
    //SET GBEMU_5, C
    //#0xE9:
    parentObj => {
      parentObj.registerC |= GBEMU_0x20;
    },
    //SET GBEMU_5, D
    //#0xEA:
    parentObj => {
      parentObj.registerD |= GBEMU_0x20;
    },
    //SET GBEMU_5, E
    //#0xEB:
    parentObj => {
      parentObj.registerE |= GBEMU_0x20;
    },
    //SET GBEMU_5, H
    //#0xEC:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x2000;
    },
    //SET GBEMU_5, L
    //#0xED:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x20;
    },
    //SET GBEMU_5, (HL)
    //#0xEE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x20
      );
    },
    //SET GBEMU_5, A
    //#0xEF:
    parentObj => {
      parentObj.registerA |= GBEMU_0x20;
    },
    //SET GBEMU_6, B
    //#0xF0:
    parentObj => {
      parentObj.registerB |= GBEMU_0x40;
    },
    //SET GBEMU_6, C
    //#0xF1:
    parentObj => {
      parentObj.registerC |= GBEMU_0x40;
    },
    //SET GBEMU_6, D
    //#0xF2:
    parentObj => {
      parentObj.registerD |= GBEMU_0x40;
    },
    //SET GBEMU_6, E
    //#0xF3:
    parentObj => {
      parentObj.registerE |= GBEMU_0x40;
    },
    //SET GBEMU_6, H
    //#0xF4:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x4000;
    },
    //SET GBEMU_6, L
    //#0xF5:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x40;
    },
    //SET GBEMU_6, (HL)
    //#0xF6:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x40
      );
    },
    //SET GBEMU_6, A
    //#0xF7:
    parentObj => {
      parentObj.registerA |= GBEMU_0x40;
    },
    //SET GBEMU_7, B
    //#0xF8:
    parentObj => {
      parentObj.registerB |= GBEMU_0x80;
    },
    //SET GBEMU_7, C
    //#0xF9:
    parentObj => {
      parentObj.registerC |= GBEMU_0x80;
    },
    //SET GBEMU_7, D
    //#0xFA:
    parentObj => {
      parentObj.registerD |= GBEMU_0x80;
    },
    //SET GBEMU_7, E
    //#0xFB:
    parentObj => {
      parentObj.registerE |= GBEMU_0x80;
    },
    //SET GBEMU_7, H
    //#0xFC:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x8000;
    },
    //SET GBEMU_7, L
    //#0xFD:
    parentObj => {
      parentObj.registersHL |= GBEMU_0x80;
    },
    //SET GBEMU_7, (HL)
    //#0xFE:
    parentObj => {
      parentObj.memoryWriter[parentObj.registersHL](
        parentObj,
        parentObj.registersHL,
        parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x80
      );
    },
    //SET GBEMU_7, A
    //#0xFF:
    parentObj => {
      parentObj.registerA |= GBEMU_0x80;
    }
  ];
  tickTable: TNextArray | number[] = [
    //Number of machine cycles for each instruction:
    GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_20, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //0
    GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //1
    GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //2
    GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_12, GBEMU_4, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //3

    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //4
    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //5
    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //6
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //7

    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //8
    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //9
    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //A
    GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //B

    GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_16, GBEMU_12, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, 0, GBEMU_12, GBEMU_24, GBEMU_8, GBEMU_16, //C
    GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_4, GBEMU_12, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, GBEMU_4, GBEMU_12, GBEMU_4, GBEMU_8, GBEMU_16, //D
    GBEMU_12, GBEMU_12, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_16, GBEMU_4, GBEMU_16, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_16, //E
    GBEMU_12, GBEMU_12, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, GBEMU_8, GBEMU_16, GBEMU_4, 0, GBEMU_4, GBEMU_8, GBEMU_16 //F
  ];
  secondaryTickTable: TNextArray | number[] = [
    //Number of machine cycles for each 0xCBXX instruction:
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //0
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //1
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //2
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //3

    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //4
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //5
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //6
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //7

    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //8
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //9
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //A
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //B

    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //C
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //D
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //E
    GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8 //F
  ];

  constructor(canvas: GameBoyCanvas, romImage: string) {
    this.canvas = canvas; //Canvas DOM object for drawing out the graphics to.
    this.romImage = romImage;
    this.updateGBBGPalette = this.updateGBColorizedBGPalette;
    this.updateGBOBJPalette = this.updateGBRegularOBJPalette;
    //Compile the LCD controller functions.
    this.initializeLCDController();
    this.initializeAudioStartState();
    this.initializeTiming();
    //Initialize the white noise cache tables ahead of time:
    this.intializeWhiteNoise();
  }
  returnFromRTCState(): void {
    //debugLog('This is returnFromRTCState');
    if (typeof this.openRTC === 'function' && this.cTimeR) {
      let rtcData: Array<number | boolean> = this.openRTC(this.name);
      let index: number = 0;
      this.lastIteration = rtcData[index++] as number;
      this.rtcIsLatched = rtcData[index++] as boolean;
      this.latchedSeconds = rtcData[index++] as number;
      this.latchedMinutes = rtcData[index++] as number;
      this.latchedHours = rtcData[index++] as number;
      this.latchedLDays = rtcData[index++] as number;
      this.latchedHDays = rtcData[index++] as number;
      this.rtcSeconds = rtcData[index++] as number;
      this.rtcMinutes = rtcData[index++] as number;
      this.rtcHours = rtcData[index++] as number;
      this.rtcDays = rtcData[index++] as number;
      this.rtcDayOverFlow = rtcData[index++] as boolean;
      this.rtcHalt = rtcData[index] as boolean;
    }
  }
  start(): void {
    //debugLog('This is GameBoyCore-start');
    this.initMemory(); //Write the startup memory.
    this.romLoad(); //Load the rom into memory and get cartridge information from it.
    this.initLCD(); //Initialize the graphics.
    this.initSound(); //Sound object initialization.
    this.run(); //Start the emulation.
  }
  initMemory(): void {
    //debugLog('This is initMemory');
    //Initialize the RAM:
    this.memory = this.getTypedArray(GBEMU_0x10000, 0, 'uint8');
    this.frameBuffer = this.getTypedArray(GBEMU_23040, GBEMU_0xF8F8F8, 'int32');
    this.bgCHRBank1.array = this.getTypedArray(GBEMU_0x800, 0, 'uint8');
    this.tickTable = this.toTypedArray(this.tickTable as TNextArray, 'uint8');
    this.secondaryTickTable = this.toTypedArray(this.secondaryTickTable as TNextArray, 'uint8');
    this.channel3PCM = this.getTypedArray(GBEMU_0x20, 0, 'int8');
  }
  generateCacheArray(tileAmount: number): Array<ArrayObject> {
    //debugLog('This is generateCacheArray');
    let tileArray: Array<ArrayObject> = [];
    let tileNumber: number = 0;
    while (tileNumber < tileAmount) {
      let object = new ArrayObject();
      object.array = this.getTypedArray(GBEMU_64, 0, 'uint8');
      tileArray[tileNumber] = object;
      tileNumber += 1;
    }
    return tileArray;
  }
  initSkipBootstrap(): void {
    //debugLog('This is initSkipBootstrap');
    let index: number = GBEMU_0xFF;
    while (index >= 0) {
      if (index >= GBEMU_0x30 && index < GBEMU_0x40) {
        this.memoryWrite(GBEMU_0xFF00 | index, this.ffxxDump[index]);
      } else {
        switch (index) {
          case GBEMU_0x00:
          case GBEMU_0x01:
          case GBEMU_0x02:
          case GBEMU_0x05:
          case GBEMU_0x07:
          case GBEMU_0x0F:
          case GBEMU_0xFF:
            this.memoryWrite(GBEMU_0xFF00 | index, this.ffxxDump[index]);
            break;
          default:
            this.memory[GBEMU_0xFF00 | index] = this.ffxxDump[index];
        }
      }
      index -= 1;
    }
    if (this.cGBC) {
      this.memory[GBEMU_0xFF6C] = GBEMU_0xFE;
      this.memory[GBEMU_0xFF74] = GBEMU_0xFE;
    } else {
      this.memory[GBEMU_0xFF48] = GBEMU_0xFF;
      this.memory[GBEMU_0xFF49] = GBEMU_0xFF;
      this.memory[GBEMU_0xFF6C] = GBEMU_0xFF;
      this.memory[GBEMU_0xFF74] = GBEMU_0xFF;
    }
    cout('Starting without the GBC boot rom.', 0);
    this.registerA = this.cGBC ? GBEMU_0x11 : GBEMU_0x1;
    this.registerB = 0;
    this.registerC = GBEMU_0x13;
    this.registerD = 0;
    this.registerE = GBEMU_0xD8;
    this.fZero = true;
    this.fSubtract = false;
    this.fHalfCarry = true;
    this.fCarry = true;
    this.registersHL = GBEMU_0x014D;
    this.lcdControl = this.lineControl;
    this.ime = false;
    this.irqLineMatched = 0;
    this.interruptsRequested = GBEMU_225;
    this.interruptsEnabled = 0;
    this.hdmaRunning = false;
    this.cpuTicks = GBEMU_12;
    this.statTracker = 0;
    this.modeSTAT = 1;
    this.spriteCount = GBEMU_252;
    this.lycMatchTriggerSTAT = false;
    this.mode2TriggerSTAT = false;
    this.mode1TriggerSTAT = false;
    this.mode0TriggerSTAT = false;
    this.lcdIsOn = true;
    this.channel1FrequencyTracker = GBEMU_0x2000;
    this.channel1DutyTracker = 0;
    this.channel1CachedDuty = this.dutyLookup[GBEMU_2];
    this.channel1totalLength = 0;
    this.channel1envelopeVolume = GBEMU_0;
    this.channel1envelopeType = false;
    this.channel1envelopeSweeps = 0;
    this.channel1envelopeSweepsLast = GBEMU_0;
    this.channel1consecutive = true;
    this.channel1frequency = GBEMU_1985;
    this.channel1SweepFault = true;
    this.channel1ShadowFrequency = GBEMU_1985;
    this.channel1timeSweep = 1;
    this.channel1lastTimeSweep = 0;
    this.channel1numSweep = GBEMU_0;
    this.channel1frequencySweepDivider = 0;
    this.channel1decreaseSweep = false;
    this.channel2FrequencyTracker = GBEMU_0x2000;
    this.channel2DutyTracker = 0;
    this.channel2CachedDuty = this.dutyLookup[GBEMU_2];
    this.channel2totalLength = 0;
    this.channel2envelopeVolume = GBEMU_0;
    this.channel2envelopeType = false;
    this.channel2envelopeSweeps = 0;
    this.channel2envelopeSweepsLast = 0;
    this.channel2consecutive = true;
    this.channel2frequency = GBEMU_0;
    this.channel3canPlay = false;
    this.channel3totalLength = 0;
    this.channel3patternType = GBEMU_4;
    this.channel3frequency = 0;
    this.channel3consecutive = true;
    this.channel3Counter = GBEMU_0x418;
    this.channel4FrequencyPeriod = GBEMU_8;
    this.channel4totalLength = 0;
    this.channel4envelopeVolume = 0;
    this.channel4currentVolume = GBEMU_0;
    this.channel4envelopeType = false;
    this.channel4envelopeSweeps = 0;
    this.channel4envelopeSweepsLast = GBEMU_0;
    this.channel4consecutive = true;
    this.channel4BitRange = GBEMU_0x7FFF;
    this.channel4VolumeShifter = GBEMU_15;
    this.channel1FrequencyCounter = GBEMU_0x200;
    this.channel2FrequencyCounter = GBEMU_0x200;
    this.channel3Counter = GBEMU_0x800;
    this.channel3FrequencyPeriod = GBEMU_0x800;
    this.channel3lastSampleLookup = 0;
    this.channel4lastSampleLookup = GBEMU_0;
    this.vinLeftChannelMasterVolume = 1;
    this.vinRightChannelMasterVolume = 1;
    this.soundMasterEnabled = true;
    //left
    this.leftChannel1 = true;
    this.leftChannel2 = true;
    this.leftChannel3 = true;
    this.leftChannel4 = true;
    //right
    this.rightChannel1 = true;
    this.rightChannel2 = true;
    this.rightChannel3 = false;
    this.rightChannel4 = false;
    this.divTicks = GBEMU_27044;
    this.lcdTicks = GBEMU_160;
    this.timerTicks = 0;
    this.timaEnabled = false;
    this.tacClocker = GBEMU_1024;
    this.serialTimer = 0;
    this.serialShiftTimer = 0;
    this.serialShiftTimerAllocated = 0;
    this.irqEnableDelay = 0;
    this.actualScanLine = GBEMU_144;
    this.lastUnrenderedLine = GBEMU_0;
    this.gfxWindowDisplay = false;
    this.gfxSpriteShow = false;
    this.gfxSpriteNormalHeight = true;
    this.bgEnabled = true;
    this.bgPriorityEnabled = true;
    this.gfxWindowCHRBankPosition = GBEMU_0;
    this.gfxBackgroundCHRBankPosition = 0;
    this.gfxBackgroundBankOffset = 0;
    this.windowY = GBEMU_0;
    this.windowX = 0;
    this.drewBlank = GBEMU_0;
    this.midScanlineOffset = -1;
    this.currentX = GBEMU_0;
  }
  initBootstrap(): void {
    //debugLog('This is initBootstrap')
    //Start as an unset device:
    cout('Starting the selected boot rom.', 0);
    this.programCounter = 0;
    this.stackPointer = 0;
    this.ime = false;
    this.lcdTicks = GBEMU_0;
    this.divTicks = 0;
    this.registerA = GBEMU_0;
    this.registerB = 0;
    this.registerC = GBEMU_0;
    this.registerD = 0;
    this.registerE = GBEMU_0;
    this.fZero = false;
    this.fSubtract = false;
    this.fHalfCarry = false;
    this.fCarry = false;
    this.registersHL = GBEMU_0;
    //left
    this.leftChannel1 = false;
    this.leftChannel2 = false;
    this.leftChannel3 = false;
    this.leftChannel4 = false;
    //right
    this.rightChannel1 = false;
    this.rightChannel2 = false;
    this.rightChannel3 = false;
    this.rightChannel4 = false;
    this.channel2frequency = GBEMU_0;
    this.channel1frequency = GBEMU_0;
    this.channel4consecutive = false;
    this.channel2consecutive = false;
    this.channel1consecutive = false;
    this.vinLeftChannelMasterVolume = GBEMU_8;
    this.vinRightChannelMasterVolume = GBEMU_8;
    this.memory[GBEMU_0xFF00] = GBEMU_0xF; //Set the joypad state.
  }
  romLoad(): void {
    //debugLog('This is romLoad');
    //Load the first two rom banks (0x0000 - 0x7FFF) into regular gameboy memory:
    this.rom = [] as Object as TNextArray;
    this.usedBootrom = settings[1] as boolean;
    let maxLength: number = this.romImage.length;
    if (maxLength < GBEMU_0x4000) {
      return;
    }
    this.rom = this.getTypedArray(maxLength, 0, 'uint8');
    let romIndex: number = 0;
    if (this.usedBootrom) {
      if (!settings[GBEMU_11]) {
        //Patch in the GBC boot rom into the memory map:
        while (romIndex < GBEMU_0x100) {
          this.memory[romIndex] = this.gbCBOOTrom[romIndex]; //Load in the GameBoy Color BOOT rom.
          this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
          romIndex += 1;
        }
        while (romIndex < GBEMU_0x200) {
          this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
          this.memory[romIndex] = this.rom[romIndex];
          romIndex += 1;
        }
        while (romIndex < GBEMU_0x900) {
          this.memory[romIndex] = this.gbCBOOTrom[romIndex - GBEMU_0x100]; //Load in the GameBoy Color BOOT rom.
          this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
          romIndex += 1;
        }
        this.usedGBCBootrom = true;
      } else {
        //Patch in the GBC boot rom into the memory map:
        while (romIndex < GBEMU_0x100) {
          this.memory[romIndex] = this.gbBOOTrom[romIndex]; //Load in the GameBoy Color BOOT rom.
          this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
          romIndex += 1;
        }
      }
      while (romIndex < GBEMU_0x4000) {
        this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
        this.memory[romIndex] = this.rom[romIndex];
        romIndex += 1;
      }
    } else {
      //Don't load in the boot rom:
      while (romIndex < GBEMU_0x4000) {
        this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
        this.memory[romIndex] = this.rom[romIndex];
        romIndex += 1;
      }
    }
    //Finish the decoding of the rom binary:
    while (romIndex < maxLength) {
      this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF;
      romIndex += 1;
    }
    this.romBankEdge = Math.floor(this.rom.length / GBEMU_0x4000);
    //Set up the emulator for the cartidge specifics:
    this.interpretCartridge();
    //Check for IRQ matching upon initialization:
    this.checkIRQMatching();
  }
  getromImage(): string | number {
    //Return the binary version of the rom image currently running:
    if (this.romImage.length > 0) {
      return this.romImage.length;
    }
    let length = this.rom.length;
    for (let index = 0; index < length; index++) {
      this.romImage += String.fromCharCode(this.rom[index]);
    }
    return this.romImage;
  }
  interpretCartridge(): void {
    //debugLog('This is interpretCartridge');
    // rom name
    for (let index = GBEMU_0x134; index < GBEMU_0x13F; index++) {
      if (this.romImage.charCodeAt(index) > 0) {
        this.name += this.romImage[index];
      }
    }
    // rom game code (for newer games)
    for (let index = GBEMU_0x13F; index < GBEMU_0x143; index++) {
      if (this.romImage.charCodeAt(index) > 0) {
        this.gameCode += this.romImage[index];
      }
    }
    cout('Game Code: ' + this.gameCode, 0);
    // Cartridge type
    this.cartridgeType = this.rom[GBEMU_0x147];
    cout('Cartridge type #' + this.cartridgeType, 0);
    //Map out rom cartridge sub-types.
    let mbcType = '';
    switch (this.cartridgeType) {
      case GBEMU_0x00:
        //rom w/o bank switching
        if (!settings[GBEMU_9]) {
          mbcType = 'rom';
          break;
        }
      case GBEMU_0x01:
        this.cMBC1 = true;
        mbcType = 'MBC1';
        break;
      case GBEMU_0x02:
        this.cMBC1 = true;
        this.cSRAM = true;
        mbcType = 'MBC1 + SRAM';
        break;
      case GBEMU_0x03:
        this.cMBC1 = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'MBC1 + SRAM + BATT';
        break;
      case GBEMU_0x05:
        this.cMBC2 = true;
        mbcType = 'MBC2';
        break;
      case GBEMU_0x06:
        this.cMBC2 = true;
        this.cBATT = true;
        mbcType = 'MBC2 + BATT';
        break;
      case GBEMU_0x08:
        this.cSRAM = true;
        mbcType = 'rom + SRAM';
        break;
      case GBEMU_0x09:
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'rom + SRAM + BATT';
        break;
      case GBEMU_0x0B:
        this.cMMMO1 = true;
        mbcType = 'MMMO1';
        break;
      case GBEMU_0x0C:
        this.cMMMO1 = true;
        this.cSRAM = true;
        mbcType = 'MMMO1 + SRAM';
        break;
      case GBEMU_0x0D:
        this.cMMMO1 = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'MMMO1 + SRAM + BATT';
        break;
      case GBEMU_0x0F:
        this.cMBC3 = true;
        this.cTimeR = true;
        this.cBATT = true;
        mbcType = 'MBC3 + TimeR + BATT';
        break;
      case GBEMU_0x10:
        this.cMBC3 = true;
        this.cTimeR = true;
        this.cBATT = true;
        this.cSRAM = true;
        mbcType = 'MBC3 + TimeR + BATT + SRAM';
        break;
      case GBEMU_0x11:
        this.cMBC3 = true;
        mbcType = 'MBC3';
        break;
      case GBEMU_0x12:
        this.cMBC3 = true;
        this.cSRAM = true;
        mbcType = 'MBC3 + SRAM';
        break;
      case GBEMU_0x13:
        this.cMBC3 = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'MBC3 + SRAM + BATT';
        break;
      case GBEMU_0x19:
        this.cMBC5 = true;
        mbcType = 'MBC5';
        break;
      case GBEMU_0x1A:
        this.cMBC5 = true;
        this.cSRAM = true;
        mbcType = 'MBC5 + SRAM';
        break;
      case GBEMU_0x1B:
        this.cMBC5 = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'MBC5 + SRAM + BATT';
        break;
      case GBEMU_0x1C:
        this.cRUMBLE = true;
        mbcType = 'RUMBLE';
        break;
      case GBEMU_0x1D:
        this.cRUMBLE = true;
        this.cSRAM = true;
        mbcType = 'RUMBLE + SRAM';
        break;
      case GBEMU_0x1E:
        this.cRUMBLE = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'RUMBLE + SRAM + BATT';
        break;
      case GBEMU_0x1F:
        this.cCamera = true;
        mbcType = 'GameBoy Camera';
        break;
      case GBEMU_0x22:
        this.cMBC7 = true;
        this.cSRAM = true;
        this.cBATT = true;
        mbcType = 'MBC7 + SRAM + BATT';
        break;
      case GBEMU_0xFD:
        this.cTAMA5 = true;
        mbcType = 'TAMA5';
        break;
      case GBEMU_0xFE:
        this.cHuC3 = true;
        mbcType = 'HuC3';
        break;
      case GBEMU_0xFF:
        this.cHuC1 = true;
        mbcType = 'HuC1';
        break;
      default:
        mbcType = 'Unknown';
        cout('Cartridge type is unknown.', GBEMU_2);
        pausePlay();
    }
    cout('Cartridge Type: ' + mbcType + '.', 0);
    // rom and RAM banks
    this.numRomBanks = this.romBanks.get(this.rom[GBEMU_0x148]) as number;
    cout(this.numRomBanks + ' rom banks.', 0);
    switch (this.ramBanks[this.rom[GBEMU_0x149]]) {
      case 0:
        cout('No RAM banking requested for allocation or MBC is of type GBEMU_2.', 0);
        break;
      case GBEMU_2:
        cout('1 RAM bank requested for allocation.', 0);
        break;
      case GBEMU_3:
        cout('GBEMU_4 RAM banks requested for allocation.', 0);
        break;
      case GBEMU_4:
        cout('GBEMU_16 RAM banks requested for allocation.', 0);
        break;
      default:
        cout('RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.', 0);
    }
    //Check the GB/GBC mode byte:
    if (!this.usedBootrom) {
      switch (this.rom[GBEMU_0x143]) {
        case GBEMU_0x00: //Only GB mode
          this.cGBC = false;
          cout('Only GB mode detected.', 0);
          break;
        case GBEMU_0x32: //Exception to the GBC identifying code:
          if (!settings[GBEMU_2] && this.name + this.gameCode + this.rom[GBEMU_0x143] === 'Game and Watch GBEMU_50') {
            this.cGBC = true;
            cout('Created a boot exception for Game and Watch Gallery GBEMU_2 (GBC ID byte is wrong on the cartridge).', 1);
          } else {
            this.cGBC = false;
          }
          break;
        case GBEMU_0x80: //Both GB + GBC modes
          this.cGBC = !settings[GBEMU_2];
          cout('GB and GBC mode detected.', 0);
          break;
        case GBEMU_0xC0: //Only GBC mode
          this.cGBC = true;
          cout('Only GBC mode detected.', 0);
          break;
        default:
          this.cGBC = false;
          cout('Unknown GameBoy game type code #' + this.rom[GBEMU_0x143] + ', defaulting to GB mode (Old games dont have a type code).', 1);
      }
      this.inBootstrap = false;
      //CPU/(V)RAM initialization.
      this.setupRAM();
      this.initSkipBootstrap();
      // Line added for benchmarking.
      this.initializeAudioStartState();
    } else {
      // AAllow the GBC boot ROM to run in GBC mode...
      this.cGBC = this.usedGBCBootrom;
      //CPU/(V)RAM initialization.
      this.setupRAM();
      this.initBootstrap();
    }
    this.initializeModeSpecificArrays();
    let cOldLicense = this.rom[GBEMU_0x14B];
    let cNewLicense = (this.rom[GBEMU_0x144] & GBEMU_0xFF00) | (this.rom[GBEMU_0x145] & GBEMU_0xFF);
    if (cOldLicense !== GBEMU_0x33) {
      //Old Style License Header
      cout('Old style license code: ' + cOldLicense, 0);
    } else {
      //New Style License Header
      cout('New style license code: ' + cNewLicense, 0);
    }
    this.romImage = ''; //Memory consumption reduction.
  }
  disableBootrom(): void {
    //debugLog('This is disableBootrom');
    //Remove any traces of the boot rom from rom memory.
    for (let index = 0; index < GBEMU_0x100; ++index) {
      this.memory[index] = this.rom[index]; //Replace the GameBoy or GameBoy Color boot rom with the game rom.
    }
    if (this.usedGBCBootrom) {
      //Remove any traces of the boot rom from rom memory.
      for (let index = GBEMU_0x200; index < GBEMU_0x900; ++index) {
        this.memory[index] = this.rom[index]; //Replace the GameBoy Color boot rom with the game rom.
      }
      if (!this.cGBC) {
        //Clean up the post-boot (GB mode only) state:
        this.gBCtoGBModeAdjust();
      } else {
        this.recompileBootIOWriteHandling();
      }
    } else {
      this.recompileBootIOWriteHandling();
    }
  }
  initializeTiming(): void {
    //debugLog('This is initializeTiming');
    //Emulator Timing:
    this.baseCPUCyclesPerIteration = (GBEMU_0x80000 / GBEMU_0x7D) * (settings[GBEMU_6] as number);
    this.cpuCyclesTotalRoundoff = this.baseCPUCyclesPerIteration % GBEMU_4;
    this.cpuCyclesTotal = (this.baseCPUCyclesPerIteration - this.cpuCyclesTotalRoundoff) | 0;
    this.cpuCyclesTotalBase = this.cpuCyclesTotal;
    this.cpuCyclesTotalCurrent = 0;
  }
  setupRAM(): void {
    //debugLog('This is setupRAM');
    //Setup the auxilliary/switchable RAM:
    if (this.cMBC2) {
      this.numRamBanks = 1 / GBEMU_16;
    } else if (this.cMBC1 || this.cRUMBLE || this.cMBC3 || this.cHuC3) {
      this.numRamBanks = GBEMU_4;
    } else if (this.cMBC5) {
      this.numRamBanks = GBEMU_16;
    } else if (this.cSRAM) {
      this.numRamBanks = 1;
    }
    if (this.numRamBanks > 0) {
      if (!this.mBCRAMUtilized()) {
        //For rom and unknown MBC cartridges using the external RAM:
        this.mbcRamBanksEnabled = true;
      }
      //Switched RAM Used
      let mbcRam: Object[] = typeof this.openMBC === 'function' ? this.openMBC(this.name) : [];
      if (mbcRam.length > 0) {
        //Flash the SRAM into memory:
        this.mbcRam = this.toTypedArray(mbcRam as Object as TNextArray, 'uint8');
      } else {
        this.mbcRam = this.getTypedArray(this.numRamBanks * GBEMU_0x2000, 0, 'uint8');
      }
    }
    cout('Actual bytes of MBC RAM allocated: ' + this.numRamBanks * GBEMU_0x2000, 0);
    this.returnFromRTCState();
    //Setup the RAM for GBC mode.
    if (this.cGBC) {
      this.vram = this.getTypedArray(GBEMU_0x2000, 0, 'uint8');
      this.gbcMemory = this.getTypedArray(GBEMU_0x7000, 0, 'uint8');
    }
    this.memoryReadJumpCompile();
    this.memoryWriteJumpCompile();
  }
  mBCRAMUtilized(): boolean {
    //debugLog('This is MBCRAMUtilized');
    return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cMBC7 || this.cRUMBLE;
  }
  recomputeDimension(): void {
    //debugLog('This is recomputeDimension');
    initNewCanvas();
    //Cache some dimension info:
    this.onscreenWidth = this.canvas!.width;
    this.onscreenHeight = this.canvas!.height;
    // The following line was modified for benchmarking:
    if (gameBoyWindow.mozRequestAnimationFrame) {
      //Firefox slowness hack:
      this.onscreenWidth = !settings[GBEMU_12] ? GBEMU_160 : this.canvas!.width;
      this.canvas!.width = this.onscreenWidth;
      this.onscreenHeight = !settings[GBEMU_12] ? GBEMU_144 : this.canvas!.height;
      this.canvas!.height = this.onscreenHeight;
    } else {
      this.onscreenWidth = this.canvas!.width;
      this.onscreenHeight = this.canvas!.height;
    }
    this.offscreenWidth = !settings[GBEMU_12] ? GBEMU_160 : this.canvas!.width;
    this.offscreenHeight = !settings[GBEMU_12] ? GBEMU_144 : this.canvas!.height;
    this.offscreenRGBCount = this.offscreenWidth * this.offscreenHeight * GBEMU_4;
  }
  initLCD(): void {
    //debugLog('This is initLCD');
    this.recomputeDimension();
    if (this.offscreenRGBCount !== GBEMU_92160) {
      //Only create the resizer handle if we need it:
      this.compileResizeFrameBufferFunction();
    } else {
      //Resizer not needed:
      this.resizer = null;
    }
    this.canvasOffscreen = new GameBoyCanvas(); // Line modified for benchmarking.
    this.canvasOffscreen.width = this.offscreenWidth;
    this.canvasOffscreen.height = this.offscreenHeight;
    this.drawContextOffscreen = this.canvasOffscreen.getContext('2d');
    this.drawContextOnscreen = this.canvas!.getContext('2d');
    //Get a CanvasPixelArray buffer:
    this.canvasBuffer = this.drawContextOffscreen.createImageData(this.offscreenWidth, this.offscreenHeight);
    let index = this.offscreenRGBCount;
    while (index > 0) {
      index -= GBEMU_4;
      this.canvasBuffer.data[index] = GBEMU_0xF8;
      this.canvasBuffer.data[index + 1] = GBEMU_0xF8;
      this.canvasBuffer.data[index + GBEMU_2] = GBEMU_0xF8;
      this.canvasBuffer.data[index + GBEMU_3] = GBEMU_0xFF;
    }
    this.graphicsBlit();
    this.canvas!.style.visibility = 'visible';
    if (this.swizzledFrame === null || this.swizzledFrame.length === 0) {
      this.swizzledFrame = this.getTypedArray(GBEMU_69120, GBEMU_0xFF, 'uint8');
    }
    //Test the draw system and browser vblank latching:
    this.drewFrame = true; //Copy the latest graphics to buffer.
    this.requestDraw();
  }
  graphicsBlit(): void {
    //debugLog('This is graphicsBlit');
    if (this.offscreenWidth === this.onscreenWidth && this.offscreenHeight === this.onscreenHeight) {
      this.drawContextOnscreen!.putImageData(this.canvasBuffer as GameBoyContextImageDataResult, 0, 0);
    } else {
      this.drawContextOffscreen!.putImageData(this.canvasBuffer as GameBoyContextImageDataResult, 0, 0);
      this.drawContextOnscreen!.drawImage(this.canvasOffscreen as GameBoyCanvas, 0, 0, this.onscreenWidth, this.onscreenHeight);
    }
  }
  joyPadEvent(key: number, down: boolean): void {
    if (down) {
      this.joyPad &= GBEMU_0xFF ^ (1 << key);
      if (!this.cGBC && (!this.usedBootrom || !this.usedGBCBootrom)) {
        this.interruptsRequested |= GBEMU_0x10; //A real GBC doesn't set this!
        this.remainingClocks = 0;
        this.checkIRQMatching();
      }
    } else {
      this.joyPad |= 1 << key;
    }
    this.memory[GBEMU_0xFF00] =
      (this.memory[GBEMU_0xFF00] & GBEMU_0x30) +
      (((this.memory[GBEMU_0xFF00] & GBEMU_0x20) === 0 ? this.joyPad >> GBEMU_4 : GBEMU_0xF) &
        ((this.memory[GBEMU_0xFF00] & GBEMU_0x10) === 0 ? this.joyPad & GBEMU_0xF : GBEMU_0xF));
    this.cpuStopped = false;
  }
  gyroEvent(xTemp: number, yTemp: number): void {
    let x = xTemp;
    let y = yTemp;
    x *= -GBEMU_100;
    x += GBEMU_2047;
    this.highX = x >> GBEMU_8;
    this.lowX = x & GBEMU_0xFF;
    y *= -GBEMU_100;
    y += GBEMU_2047;
    this.highY = y >> GBEMU_8;
    this.lowY = y & GBEMU_0xFF;
  }
  initSound(): void {
    //debugLog('This is initSound');
    this.sampleSize = (GBEMU_0x400000 / GBEMU_1000) * (settings[GBEMU_6] as number);
    this.machineOut = settings[GBEMU_13] as number;
    if (settings[0]) {
      let _ = this;
      this.audioHandle = new XAudioServer(
        GBEMU_2,
        GBEMU_0x400000 / (settings[GBEMU_13] as number),
        0,
        Math.max((this.sampleSize * (settings[GBEMU_8] as number)) / (settings[GBEMU_13] as number), GBEMU_8192) << 1,
        null,
        settings[GBEMU_14] as number
      );
      this.initAudioBuffer();
    } else if (this.audioHandle) {
      //Mute the audio output, as it has an immediate silencing effect:
      this.audioHandle.changeVolume(0);
    }
  }
  changeVolume(): void {
    if (settings[0] && this.audioHandle) {
      this.audioHandle.changeVolume(settings[GBEMU_14] as number);
    }
  }
  initAudioBuffer(): void {
    //debugLog('This is initAudioBuffer');
    this.audioIndex = 0;
    this.bufferContainAmount = Math.max((this.sampleSize * (settings[GBEMU_7] as number)) / (settings[GBEMU_13] as number), GBEMU_4096) << 1;
    this.numSamplesTotal = (this.sampleSize - (this.sampleSize % (settings[GBEMU_13] as number))) | 0;
    this.currentBuffer = this.getTypedArray(this.numSamplesTotal, GBEMU_0xF0F0, 'int32');
    this.secondaryBuffer = this.getTypedArray((this.numSamplesTotal << 1) / (settings[GBEMU_13] as number), 0, 'float32');
  }
  intializeWhiteNoise(): void {
    //debugLog('This is intializeWhiteNoise');
    //Noise Sample Tables:
    let randomFactor: number = 1;
    //GBEMU_15-bit lsfr Cache Generation:
    this.lsfr15Table = this.getTypedArray(GBEMU_0x80000, 0, 'int8');
    let lsfr: number = GBEMU_0x7FFF; //Seed value has all its bits set.
    let lsfrShifted: number = GBEMU_0x3FFF;
    for (let index = 0; index < GBEMU_0x8000; ++index) {
      //Normalize the last lsfr value for usage:
      randomFactor = 1 - (lsfr & 1); //Docs say it's the inverse.
      //Cache the different volume level results:
      this.lsfr15Table[GBEMU_0x08000 | index] = randomFactor;
      this.lsfr15Table[GBEMU_0x10000 | index] = randomFactor * GBEMU_0x2;
      this.lsfr15Table[GBEMU_0x18000 | index] = randomFactor * GBEMU_0x3;
      this.lsfr15Table[GBEMU_0x20000 | index] = randomFactor * GBEMU_0x4;
      this.lsfr15Table[GBEMU_0x28000 | index] = randomFactor * GBEMU_0x5;
      this.lsfr15Table[GBEMU_0x30000 | index] = randomFactor * GBEMU_0x6;
      this.lsfr15Table[GBEMU_0x38000 | index] = randomFactor * GBEMU_0x7;
      this.lsfr15Table[GBEMU_0x40000 | index] = randomFactor * GBEMU_0x8;
      this.lsfr15Table[GBEMU_0x48000 | index] = randomFactor * GBEMU_0x9;
      this.lsfr15Table[GBEMU_0x50000 | index] = randomFactor * GBEMU_0xA;
      this.lsfr15Table[GBEMU_0x58000 | index] = randomFactor * GBEMU_0xB;
      this.lsfr15Table[GBEMU_0x60000 | index] = randomFactor * GBEMU_0xC;
      this.lsfr15Table[GBEMU_0x68000 | index] = randomFactor * GBEMU_0xD;
      this.lsfr15Table[GBEMU_0x70000 | index] = randomFactor * GBEMU_0xE;
      this.lsfr15Table[GBEMU_0x78000 | index] = randomFactor * GBEMU_0xF;
      //Recompute the lsfr algorithm:
      lsfrShifted = lsfr >> 1;
      lsfr = lsfrShifted | (((lsfrShifted ^ lsfr) & GBEMU_0x1) << GBEMU_14);
    }
    //GBEMU_7-bit lsfr Cache Generation:
    this.lsfr7Table = this.getTypedArray(GBEMU_0x800, 0, 'int8');
    lsfr = GBEMU_0x7F; //Seed value has all its bits set.
    for (let index = 0; index < GBEMU_0x80; ++index) {
      //Normalize the last lsfr value for usage:
      randomFactor = 1 - (lsfr & 1); //Docs say it's the inverse.
      //Cache the different volume level results:
      this.lsfr7Table[GBEMU_0x080 | index] = randomFactor;
      this.lsfr7Table[GBEMU_0x100 | index] = randomFactor * GBEMU_0x2;
      this.lsfr7Table[GBEMU_0x180 | index] = randomFactor * GBEMU_0x3;
      this.lsfr7Table[GBEMU_0x200 | index] = randomFactor * GBEMU_0x4;
      this.lsfr7Table[GBEMU_0x280 | index] = randomFactor * GBEMU_0x5;
      this.lsfr7Table[GBEMU_0x300 | index] = randomFactor * GBEMU_0x6;
      this.lsfr7Table[GBEMU_0x380 | index] = randomFactor * GBEMU_0x7;
      this.lsfr7Table[GBEMU_0x400 | index] = randomFactor * GBEMU_0x8;
      this.lsfr7Table[GBEMU_0x480 | index] = randomFactor * GBEMU_0x9;
      this.lsfr7Table[GBEMU_0x500 | index] = randomFactor * GBEMU_0xA;
      this.lsfr7Table[GBEMU_0x580 | index] = randomFactor * GBEMU_0xB;
      this.lsfr7Table[GBEMU_0x600 | index] = randomFactor * GBEMU_0xC;
      this.lsfr7Table[GBEMU_0x680 | index] = randomFactor * GBEMU_0xD;
      this.lsfr7Table[GBEMU_0x700 | index] = randomFactor * GBEMU_0xE;
      this.lsfr7Table[GBEMU_0x780 | index] = randomFactor * GBEMU_0xF;
      //Recompute the lsfr algorithm:
      lsfrShifted = lsfr >> 1;
      lsfr = lsfrShifted | (((lsfrShifted ^ lsfr) & GBEMU_0x1) << GBEMU_6);
    }
    if (!this.noiseSampleTable && this.memory.length === GBEMU_0x10000) {
      //If enabling audio for the first time after a game is already running, set up the internal table reference:
      this.noiseSampleTable = (this.memory[GBEMU_0xFF22] & GBEMU_0x8) === GBEMU_0x8 ? this.lsfr7Table : this.lsfr15Table;
    }
  }
  audioUnderrunAdjustment(): void {
    //debugLog('This is audioUnderrunAdjustment');
    if (settings[0]) {
      let underrunAmount = this.bufferContainAmount - this.audioHandle!.remainingBuffer();
      if (underrunAmount > 0) {
        this.cpuCyclesTotalCurrent += (underrunAmount >> 1) * this.machineOut;
        this.recalculateIterationClockLimit();
      }
    }
  }
  initializeAudioStartState(): void {
    //debugLog('This is initializeAudioStartState');
    this.channel1FrequencyTracker = GBEMU_0x2000;
    this.channel1DutyTracker = 0;
    this.channel1CachedDuty = this.dutyLookup[GBEMU_2];
    this.channel1totalLength = 0;
    this.channel1envelopeVolume = GBEMU_0;
    this.channel1envelopeType = false;
    this.channel1envelopeSweeps = GBEMU_0;
    this.channel1envelopeSweepsLast = GBEMU_0;
    this.channel1consecutive = true;
    this.channel1frequency = GBEMU_0;
    this.channel1SweepFault = false;
    this.channel1ShadowFrequency = GBEMU_0;
    this.channel1timeSweep = 1;
    this.channel1lastTimeSweep = GBEMU_0;
    this.channel1numSweep = GBEMU_0;
    this.channel1frequencySweepDivider = GBEMU_0;
    this.channel1decreaseSweep = false;
    this.channel2FrequencyTracker = GBEMU_0x2000;
    this.channel2DutyTracker = 0;
    this.channel2CachedDuty = this.dutyLookup[GBEMU_2];
    this.channel2totalLength = 0;
    this.channel2envelopeVolume = 0;
    this.channel2envelopeType = false;
    this.channel2envelopeSweeps = GBEMU_0;
    this.channel2envelopeSweepsLast = 0;
    this.channel2consecutive = true;
    this.channel2frequency = GBEMU_0;
    this.channel3canPlay = false;
    this.channel3totalLength = 0;
    this.channel3patternType = GBEMU_4;
    this.channel3frequency = 0;
    this.channel3consecutive = true;
    this.channel3Counter = GBEMU_0x800;
    this.channel4FrequencyPeriod = GBEMU_8;
    this.channel4totalLength = GBEMU_0;
    this.channel4envelopeVolume = GBEMU_0;
    this.channel4currentVolume = GBEMU_0;
    this.channel4envelopeType = false;
    this.channel4envelopeSweeps = 0;
    this.channel4envelopeSweepsLast = GBEMU_0;
    this.channel4consecutive = true;
    this.channel4BitRange = GBEMU_0x7FFF;
    this.noiseSampleTable = this.lsfr15Table;
    this.channel4VolumeShifter = GBEMU_15;
    this.channel1FrequencyCounter = GBEMU_0x2000;
    this.channel2FrequencyCounter = GBEMU_0x2000;
    this.channel3Counter = GBEMU_0x800;
    this.channel3FrequencyPeriod = GBEMU_0x800;
    this.channel3lastSampleLookup = GBEMU_0;
    this.channel4lastSampleLookup = 0;
    this.vinLeftChannelMasterVolume = GBEMU_8;
    this.vinRightChannelMasterVolume = GBEMU_8;
    this.mixerOutputCache = 0;
    this.sequencerClocks = GBEMU_0x2000;
    this.sequencePosition = 0;
    this.channel4FrequencyPeriod = GBEMU_8;
    this.channel4Counter = GBEMU_8;
    this.cachedChannel3Sample = 0;
    this.cachedChannel4Sample = 0;
    //default is false
    this.channel1Enabled = false;
    this.channel2Enabled = false;
    this.channel3Enabled = false;
    this.channel4Enabled = false;
    //default is false
    this.channel1canPlay = false;
    this.channel2canPlay = false;
    this.channel4canPlay = false;
    //cahce
    this.channel1OutputLevelCache();
    this.channel2OutputLevelCache();
    this.channel3OutputLevelCache();
    this.channel4OutputLevelCache();
  }
  outputAudio(): void {
    //debugLog('This is outputAudio');
    let sampleFactor: number = 0;
    let dirtySample: number = 0;
    let averageL: number = 0;
    let averageR: number = 0;
    let destinationPosition: number = 0;
    let divisor1: number = settings[GBEMU_13] as number;
    let divisor2: number = divisor1 * GBEMU_0xF0;
    let sourcePosition: number = 0;
    while (sourcePosition < this.numSamplesTotal) {
      sampleFactor = 0;
      averageL = 0;
      averageR = 0;
      while (sampleFactor < divisor1) {
        dirtySample = this.currentBuffer[sourcePosition++];
        averageL += dirtySample >> GBEMU_9;
        averageR += dirtySample & GBEMU_0x1FF;
        sampleFactor += 1;
      }
      this.secondaryBuffer[destinationPosition++] = averageL / divisor2 - 1;
      this.secondaryBuffer[destinationPosition++] = averageR / divisor2 - 1;
    }
    this.audioHandle!.writeAudioNoCallback(this.secondaryBuffer as Float32Array);
  }
  //Below are the audio generation functions timed against the CPU:
  generateAudio(numSamplesTemp: number): void {
    //debugLog('This is generateAudio');
    let numSamples = numSamplesTemp;
    if (this.soundMasterEnabled && !this.cpuStopped) {
      let samplesToGenerate = 0;
      while (numSamples > 0) {
        samplesToGenerate = numSamples < this.sequencerClocks ? numSamples : this.sequencerClocks;
        this.sequencerClocks -= samplesToGenerate;
        numSamples -= samplesToGenerate;
        samplesToGenerate -= 1;
        while (samplesToGenerate > -1) {
          this.computeAudioChannels();
          this.currentBuffer[this.audioIndex++] = this.mixerOutputCache;
          if (this.audioIndex === this.numSamplesTotal) {
            this.audioIndex = 0;
            this.outputAudio();
          }
          samplesToGenerate -= 1;
        }
        if (this.sequencerClocks === 0) {
          this.audioComputeSequencer();
          this.sequencerClocks = GBEMU_0x2000;
        }
      }
    } else {
      //SILENT OUTPUT:
      numSamples -= 1;
      while (numSamples > -1) {
        numSamples -= 1;
        this.currentBuffer[this.audioIndex++] = GBEMU_0xF0F0;
        if (this.audioIndex === this.numSamplesTotal) {
          this.audioIndex = 0;
          this.outputAudio();
        }
      }
    }
  }
  //Generate audio, but don't actually output it (Used for when sound is disabled by user/browser):
  generateAudioFake(numSamplesTemp: number): void {
    //debugLog('This is generateAudioFake');
    if (this.soundMasterEnabled && !this.cpuStopped) {
      let numSamples = numSamplesTemp - 1;
      while (numSamples > -1) {
        this.computeAudioChannels();
        this.sequencerClocks -= 1;
        if (this.sequencerClocks === 0) {
          this.audioComputeSequencer();
          this.sequencerClocks = GBEMU_0x2000;
        }
        numSamples -= 1;
      }
    }
  }
  audioJIT(): void {
    //debugLog('This is audioJIT');
    //Audio Sample Generation Timing:
    if (settings[GBEMU_0]) {
      this.generateAudio(this.audioTicks);
    } else {
      this.generateAudioFake(this.audioTicks);
    }
    this.audioTicks = GBEMU_0;
  }
  audioComputeSequencer(): void {
    //debugLog('This is audioComputeSequencer');
    switch (this.sequencePosition++) {
      case 0:
        this.clockAudioLength();
        break;
      case GBEMU_2:
        this.clockAudioLength();
        this.clockAudioSweep();
        break;
      case GBEMU_4:
        this.clockAudioLength();
        break;
      case GBEMU_6:
        this.clockAudioLength();
        this.clockAudioSweep();
        break;
      case GBEMU_7:
        this.clockAudioEnvelope();
        this.sequencePosition = 0;
      default:
        break;
    }
  }
  clockAudioLength(): void {
    //Channel 1:
    if (this.channel1totalLength > 1) {
      this.channel1totalLength -= 1;
    } else if (this.channel1totalLength === 1) {
      this.channel1totalLength = 0;
      this.channel1EnableCheck();
      this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
    }
    //Channel GBEMU_2:
    if (this.channel2totalLength > 1) {
      this.channel2totalLength -= 1;
    } else if (this.channel2totalLength === 1) {
      this.channel2totalLength = 0;
      this.channel2EnableCheck();
      this.memory[GBEMU_0xFF26] &= GBEMU_0xFD; //Channel #GBEMU_2 On Flag Off
    }
    //Channel GBEMU_3:
    if (this.channel3totalLength > 1) {
      this.channel3totalLength -= 1;
    } else if (this.channel3totalLength === 1) {
      this.channel3totalLength = 0;
      this.channel3EnableCheck();
      this.memory[GBEMU_0xFF26] &= GBEMU_0xFB; //Channel #GBEMU_3 On Flag Off
    }
    //Channel GBEMU_4:
    if (this.channel4totalLength > 1) {
      this.channel4totalLength -= 1;
    } else if (this.channel4totalLength === 1) {
      this.channel4totalLength = 0;
      this.channel4EnableCheck();
      this.memory[GBEMU_0xFF26] &= GBEMU_0xF7; //Channel #GBEMU_4 On Flag Off
    }
  }
  clockAudioSweep(): void {
    //Channel 1:
    if (!this.channel1SweepFault && this.channel1timeSweep > 0) {
      this.channel1timeSweep -= 1;
      if (this.channel1timeSweep === 0) {
        this.runAudioSweep();
      }
    }
  }
  runAudioSweep(): void {
    //debugLog('This is runAudioSweep');
    //Channel 1:
    if (this.channel1lastTimeSweep > 0) {
      if (this.channel1frequencySweepDivider > 0) {
        if (this.channel1numSweep > 0) {
          this.channel1numSweep -= 1;
          if (this.channel1decreaseSweep) {
            this.channel1ShadowFrequency -= this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
            this.channel1frequency = this.channel1ShadowFrequency & GBEMU_0x7FF;
            this.channel1FrequencyTracker = (GBEMU_0x800 - this.channel1frequency) << GBEMU_2;
          } else {
            this.channel1ShadowFrequency += this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
            this.channel1frequency = this.channel1ShadowFrequency;
            if (this.channel1ShadowFrequency <= GBEMU_0x7FF) {
              this.channel1FrequencyTracker = (GBEMU_0x800 - this.channel1frequency) << GBEMU_2;
              //Run overflow check twice:
              if (this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider) > GBEMU_0x7ff) {
                this.channel1SweepFault = true;
                this.channel1EnableCheck();
                this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
              }
            } else {
              this.channel1frequency &= GBEMU_0x7FF;
              this.channel1SweepFault = true;
              this.channel1EnableCheck();
              this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
            }
          }
        }
        this.channel1timeSweep = this.channel1lastTimeSweep;
      } else {
        //Channel has sweep disabled and timer becomes a length counter:
        this.channel1SweepFault = true;
        this.channel1EnableCheck();
      }
    }
  }
  clockAudioEnvelope(): void {
    //debugLog('This is clockAudioEnvelope');
    //Channel 1:
    if (this.channel1envelopeSweepsLast > -1) {
      if (this.channel1envelopeSweeps > 0) {
        this.channel1envelopeSweeps -= 1;
      } else {
        if (!this.channel1envelopeType) {
          if (this.channel1envelopeVolume > 0) {
            this.channel1envelopeVolume -= 1;
            this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
            this.channel1OutputLevelCache();
          } else {
            this.channel1envelopeSweepsLast = -1;
          }
        } else if (this.channel1envelopeVolume < GBEMU_0xF) {
          this.channel1envelopeVolume += 1;
          this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
          this.channel1OutputLevelCache();
        } else {
          this.channel1envelopeSweepsLast = -1;
        }
      }
    }
    //Channel GBEMU_2:
    if (this.channel2envelopeSweepsLast > -1) {
      if (this.channel2envelopeSweeps > 0) {
        this.channel2envelopeSweeps -= 1;
      } else {
        if (!this.channel2envelopeType) {
          if (this.channel2envelopeVolume > 0) {
            this.channel2envelopeVolume -= 1;
            this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
            this.channel2OutputLevelCache();
          } else {
            this.channel2envelopeSweepsLast = -1;
          }
        } else if (this.channel2envelopeVolume < GBEMU_0xf) {
          this.channel2envelopeVolume += 1;
          this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
          this.channel2OutputLevelCache();
        } else {
          this.channel2envelopeSweepsLast = -1;
        }
      }
    }
    //Channel GBEMU_4:
    if (this.channel4envelopeSweepsLast > -1) {
      if (this.channel4envelopeSweeps > 0) {
        this.channel4envelopeSweeps -= 1;
      } else {
        if (!this.channel4envelopeType) {
          if (this.channel4envelopeVolume > 0) {
            this.channel4envelopeVolume -= 1;
            this.channel4currentVolume = this.channel4envelopeVolume << this.channel4VolumeShifter;
            this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
            this.channel4UpdateCache();
          } else {
            this.channel4envelopeSweepsLast = -1;
          }
        } else if (this.channel4envelopeVolume < GBEMU_0xF) {
          this.channel4envelopeVolume += 1;
          this.channel4currentVolume = this.channel4envelopeVolume << this.channel4VolumeShifter;
          this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
          this.channel4UpdateCache();
        } else {
          this.channel4envelopeSweepsLast = -1;
        }
      }
    }
  }
  computeAudioChannels(): void {
    //Channel 1 counter:
    this.channel1FrequencyCounter -= 1;
    if (this.channel1FrequencyCounter === 0) {
      this.channel1FrequencyCounter = this.channel1FrequencyTracker;
      this.channel1DutyTracker = (this.channel1DutyTracker + 1) & GBEMU_0x7;
      this.channel1OutputLevelTrimaryCache();
    }
    //Channel GBEMU_2 counter:
    this.channel2FrequencyCounter -= 1;
    if (this.channel2FrequencyCounter === 0) {
      this.channel2FrequencyCounter = this.channel2FrequencyTracker;
      this.channel2DutyTracker = (this.channel2DutyTracker + 1) & GBEMU_0x7;
      this.channel2OutputLevelTrimaryCache();
    }
    //Channel GBEMU_3 counter:
    this.channel3Counter -= 1;
    if (this.channel3Counter === 0) {
      if (this.channel3canPlay) {
        this.channel3lastSampleLookup = (this.channel3lastSampleLookup + 1) & GBEMU_0x1f;
      }
      this.channel3Counter = this.channel3FrequencyPeriod;
      this.channel3UpdateCache();
    }
    //Channel GBEMU_4 counter:
    this.channel4Counter -= 1;
    if (this.channel4Counter === 0) {
      this.channel4lastSampleLookup = (this.channel4lastSampleLookup + 1) & this.channel4BitRange;
      this.channel4Counter = this.channel4FrequencyPeriod;
      this.channel4UpdateCache();
    }
  }
  channel1EnableCheck(): void {
    this.channel1Enabled = (this.channel1consecutive || this.channel1totalLength > 0) && !this.channel1SweepFault && this.channel1canPlay;
    this.channel1OutputLevelSecondaryCache();
  }
  channel1VolumeEnableCheck(): void {
    this.channel1canPlay = this.memory[GBEMU_0xFF12] > GBEMU_7;
    this.channel1EnableCheck();
    this.channel1OutputLevelSecondaryCache();
  }
  channel1OutputLevelCache(): void {
    //debugLog('This is channel1OutputLevelCache');
    this.channel1currentSampleLeft = this.leftChannel1 ? this.channel1envelopeVolume : 0;
    this.channel1currentSampleRight = this.rightChannel1 ? this.channel1envelopeVolume : 0;
    this.channel1OutputLevelSecondaryCache();
  }
  channel1OutputLevelSecondaryCache(): void {
    //debugLog('This is channel1OutputLevelSecondaryCache');
    if (this.channel1Enabled) {
      //is true
      this.channel1currentSampleLeftSecondary = this.channel1currentSampleLeft;
      this.channel1currentSampleRightSecondary = this.channel1currentSampleRight;
    } else {
      //is false
      this.channel1currentSampleLeftSecondary = 0;
      this.channel1currentSampleRightSecondary = 0;
    }
    this.channel1OutputLevelTrimaryCache();
  }
  channel1OutputLevelTrimaryCache(): void {
    //debugLog('This is channel1OutputLevelTrimaryCache');
    if (this.channel1CachedDuty[this.channel1DutyTracker]) {
      //is true
      this.channel1currentSampleLeftTrimary = this.channel1currentSampleLeftSecondary;
      this.channel1currentSampleRightTrimary = this.channel1currentSampleRightSecondary;
    } else {
      // is false
      this.channel1currentSampleLeftTrimary = 0;
      this.channel1currentSampleRightTrimary = 0;
    }
    this.mixerOutputLevelCache();
  }
  channel2EnableCheck(): void {
    this.channel2Enabled = (this.channel2consecutive || this.channel2totalLength > 0) && this.channel2canPlay;
    this.channel2OutputLevelSecondaryCache();
  }
  channel2VolumeEnableCheck(): void {
    this.channel2canPlay = this.memory[GBEMU_0xFF17] > GBEMU_7;
    this.channel2EnableCheck();
    this.channel2OutputLevelSecondaryCache();
  }
  channel2OutputLevelCache(): void {
    //debugLog('This is channel2OutputLevelCache');
    this.channel2currentSampleLeft = this.leftChannel2 ? this.channel2envelopeVolume : 0;
    this.channel2currentSampleRight = this.rightChannel2 ? this.channel2envelopeVolume : 0;
    this.channel2OutputLevelSecondaryCache();
  }
  channel2OutputLevelSecondaryCache(): void {
    //debugLog('This is channel2OutputLevelSecondaryCache');
    if (this.channel2Enabled) {
      //is true
      this.channel2currentSampleLeftSecondary = this.channel2currentSampleLeft;
      this.channel2currentSampleRightSecondary = this.channel2currentSampleRight;
    } else {
      //is false
      this.channel2currentSampleLeftSecondary = 0;
      this.channel2currentSampleRightSecondary = 0;
    }
    this.channel2OutputLevelTrimaryCache();
  }
  channel2OutputLevelTrimaryCache(): void {
    //debugLog('This is channel2OutputLevelTrimaryCache');
    if (this.channel2CachedDuty[this.channel2DutyTracker]) {
      //is true
      this.channel2currentSampleLeftTrimary = this.channel2currentSampleLeftSecondary;
      this.channel2currentSampleRightTrimary = this.channel2currentSampleRightSecondary;
    } else {
      //is false
      this.channel2currentSampleLeftTrimary = 0;
      this.channel2currentSampleRightTrimary = 0;
    }
    this.mixerOutputLevelCache();
  }
  channel3EnableCheck(): void {
    this.channel3Enabled = /*this.channel3canPlay && */ this.channel3consecutive || this.channel3totalLength > 0;
    this.channel3OutputLevelSecondaryCache();
  }
  channel3OutputLevelCache(): void {
    this.channel3currentSampleLeft = this.leftChannel3 ? this.cachedChannel3Sample : 0;
    this.channel3currentSampleRight = this.rightChannel3 ? this.cachedChannel3Sample : 0;
    this.channel3OutputLevelSecondaryCache();
  }
  channel3OutputLevelSecondaryCache(): void {
    if (this.channel3Enabled) {
      //is true
      this.channel3currentSampleLeftSecondary = this.channel3currentSampleLeft;
      this.channel3currentSampleRightSecondary = this.channel3currentSampleRight;
    } else {
      //is false
      this.channel3currentSampleLeftSecondary = 0;
      this.channel3currentSampleRightSecondary = 0;
    }
    this.mixerOutputLevelCache();
  }
  channel4EnableCheck(): void {
    this.channel4Enabled = (this.channel4consecutive || this.channel4totalLength > 0) && this.channel4canPlay;
    this.channel4OutputLevelSecondaryCache();
  }
  channel4VolumeEnableCheck(): void {
    this.channel4canPlay = this.memory[GBEMU_0xFF21] > GBEMU_7;
    this.channel4EnableCheck();
    this.channel4OutputLevelSecondaryCache();
  }
  channel4OutputLevelCache(): void {
    this.channel4currentSampleLeft = this.leftChannel4 ? this.cachedChannel4Sample : 0;
    this.channel4currentSampleRight = this.rightChannel4 ? this.cachedChannel4Sample : 0;
    this.channel4OutputLevelSecondaryCache();
  }
  channel4OutputLevelSecondaryCache(): void {
    if (this.channel4Enabled) {
      //is true
      this.channel4currentSampleLeftSecondary = this.channel4currentSampleLeft;
      this.channel4currentSampleRightSecondary = this.channel4currentSampleRight;
    } else {
      //is false
      this.channel4currentSampleLeftSecondary = 0;
      this.channel4currentSampleRightSecondary = 0;
    }
    this.mixerOutputLevelCache();
  }
  mixerOutputLevelCache(): void {
    this.mixerOutputCache =
      (((this.channel1currentSampleLeftTrimary +
        this.channel2currentSampleLeftTrimary +
        this.channel3currentSampleLeftSecondary +
        this.channel4currentSampleLeftSecondary) *
        this.vinLeftChannelMasterVolume) <<
        GBEMU_9) +
      (this.channel1currentSampleRightTrimary +
        this.channel2currentSampleRightTrimary +
        this.channel3currentSampleRightSecondary +
        this.channel4currentSampleRightSecondary) *
        this.vinRightChannelMasterVolume;
  }
  channel3UpdateCache(): void {
    this.cachedChannel3Sample = (this.channel3PCM as TNextArray)[this.channel3lastSampleLookup] >> this.channel3patternType;
    this.channel3OutputLevelCache();
  }
  channel3WriteRAM(addressTemp: number, data: number): void {
    let address = addressTemp;
    if (this.channel3canPlay) {
      this.audioJIT();
      //address = this.channel3lastSampleLookup >> 1;
    }
    this.memory[GBEMU_0xFF30 | address] = data;
    address <<= 1;
    (this.channel3PCM as TNextArray)[address] = data >> GBEMU_4;
    (this.channel3PCM as TNextArray)[address | 1] = data & GBEMU_0xF;
  }
  channel4UpdateCache(): void {
    this.cachedChannel4Sample = (this.noiseSampleTable as TNextArray)[this.channel4currentVolume | this.channel4lastSampleLookup];
    this.channel4OutputLevelCache();
  }
  run(): void {
    //debugLog('This is GameBoyCore run');
    //The preprocessing before the actual iteration loop:
    if ((this.stopEmulator & GBEMU_2) === 0) {
      if ((this.stopEmulator & GBEMU_1) === 1) {
        if (!this.cpuStopped) {
          this.stopEmulator = GBEMU_0;
          this.drewFrame = false;
          this.audioUnderrunAdjustment();
          //RTC clocking.
          this.clockUpdate();
          if (!this.halt) {
            this.executeIteration();
          } else {
            //Finish the HALT rundown execution.
            this.cpuTicks = GBEMU_0;
            this.calculateHALTPeriod();
            if (this.halt) {
              this.updateCoreFull(); //true
            } else {
              this.executeIteration();
            }
          }
          this.requestDraw(); //Request the graphics target to be updated
        } else {
          this.audioUnderrunAdjustment();
          this.audioTicks += this.cpuCyclesTotal;
          this.audioJIT();
          this.stopEmulator |= GBEMU_1; //End current loop.
        }
      } else {
        //We can only get here if there was an internal error, but the loop was restarted.
        cout('Iterator restarted a faulted core.', GBEMU_2);
        pausePlay();
      }
    }
  }
  executeIteration(): void {
    //debugLog('This is executeIteration');
    //Iterate the interpreter loop:
    let opcodeToExecute = 0;
    let timedTicks = 0;
    while (this.stopEmulator === 0) {
      //Interrupt Arming:
      switch (this.irqEnableDelay) {
        case GBEMU_1:
          this.ime = true;
          this.checkIRQMatching();
        case GBEMU_2:
          this.irqEnableDelay -= 1;
        default:
          break;
      }
      //Is an IRQ set to fire?:
      if (this.irqLineMatched > GBEMU_0) {
        //ime is true and and interrupt was matched:
        this.launchIRQ();
      }
      opcodeToExecute = this.memoryReader[this.programCounter](this, this.programCounter); //Fetch the current opcode
      //Increment the program counter to the next instruction:
      this.programCounter = (this.programCounter + 1) & GBEMU_0xFFFF;
      //Check for the program counter quirk:
      if (this.skipPCIncrement) {
        this.programCounter = (this.programCounter - 1) & GBEMU_0xFFFF;
        this.skipPCIncrement = false;
      }
      //Get how many CPU cycles the current instruction counts for:
      this.cpuTicks = this.tickTable[opcodeToExecute];
      //Execute the current instruction:
      this.opCode[opcodeToExecute](this);
      //Update the clocking for the LCD emulation:
      //Update the state (Inlined updateCoreFull manually here):
      this.lcdTicks += this.cpuTicks >> this.doubleSpeedShifter;
      //Scan Line and STAT Mode Control
      this.lcdControl[this.actualScanLine](this);
      //Single-speed relative timing for A/V emulation:
      timedTicks = this.cpuTicks >> this.doubleSpeedShifter;
      //Audio Timing
      this.audioTicks += timedTicks;
      //Emulator Timing
      this.emulatorTicks += timedTicks;
      //CPU Timers:
      this.divTicks += this.cpuTicks;
      if (this.timaEnabled) {
        //TIMA Timing
        this.timerTicks += this.cpuTicks;
        while (this.timerTicks >= this.tacClocker) {
          this.timerTicks -= this.tacClocker;
          this.memory[GBEMU_0xFF05] += GBEMU_1;
          if (this.memory[GBEMU_0xFF05] === GBEMU_0x100) {
            this.memory[GBEMU_0xFF05] = this.memory[GBEMU_0xFF06];
            this.interruptsRequested |= GBEMU_0x4;
            this.checkIRQMatching();
          }
        }
      }
      if (this.serialTimer > GBEMU_0) {
        //Serial Timing
        //IRQ Counter:
        this.serialTimer -= this.cpuTicks;
        if (this.serialTimer <= GBEMU_0) {
          this.interruptsRequested |= GBEMU_0x8;
          this.checkIRQMatching();
        }
        //Bit Shit Counter:
        this.serialShiftTimer -= this.cpuTicks;
        if (this.serialShiftTimer <= GBEMU_0) {
          this.serialShiftTimer = this.serialShiftTimerAllocated;
          this.memory[GBEMU_0xFF01] = ((this.memory[GBEMU_0xFF01] << GBEMU_1) & GBEMU_0xFE) | GBEMU_0x01; //We could shift in actual link data here if we were to implement such!!!
        }
      }
      //End of iteration routine:
      if (this.emulatorTicks >= this.cpuCyclesTotal) {
        this.iterationEndRoutine();
      }
      // Start of code added for benchmarking:
      this.instructions += 1;
      if (this.instructions > this.totalInstructions) {
        this.iterationEndRoutine();
        this.stopEmulator |= GBEMU_2;
        checkFinalState();
      }
      // End of code added for benchmarking.
    }
  }
  iterationEndRoutine(): void {
    //debugLog('This is iterationEndRoutine');
    if ((this.stopEmulator & GBEMU_0x1) === 0) {
      this.audioJIT(); //Make sure we at least output once per iteration.
      //Update DIV Alignment (Integer overflow safety):
      this.memory[GBEMU_0xFF04] = (this.memory[GBEMU_0xFF04] + (this.divTicks >> GBEMU_8)) & GBEMU_0xFF;
      this.divTicks &= GBEMU_0xFF;
      //Update emulator flags:
      this.stopEmulator |= 1; //End current loop.
      this.emulatorTicks -= this.cpuCyclesTotal;
      this.cpuCyclesTotalCurrent += this.cpuCyclesTotalRoundoff;
      this.recalculateIterationClockLimit();
    }
  }
  handleSTOP(): void {
    //debugLog('This is handleSTOP');
    this.cpuStopped = true; //Stop CPU until joypad input changes.
    this.iterationEndRoutine();
    if (this.emulatorTicks < 0) {
      this.audioTicks -= this.emulatorTicks;
      this.audioJIT();
    }
  }
  recalculateIterationClockLimit(): void {
    //debugLog('This is recalculateIterationClockLimit');
    let endModulus = this.cpuCyclesTotalCurrent % GBEMU_4;
    this.cpuCyclesTotal = this.cpuCyclesTotalBase + this.cpuCyclesTotalCurrent - endModulus;
    this.cpuCyclesTotalCurrent = endModulus;
  }
  scanLineMode2(): void {
    //OAM Search Period
    if (this.statTracker !== 1) {
      if (this.mode2TriggerSTAT) {
        this.interruptsRequested |= GBEMU_0x2;
        this.checkIRQMatching();
      }
      this.statTracker = 1;
      this.modeSTAT = GBEMU_2;
    }
  }
  scanLineMode3(): void {
    //Scan Line Drawing Period
    if (this.modeSTAT !== GBEMU_3) {
      if (this.statTracker === 0 && this.mode2TriggerSTAT) {
        this.interruptsRequested |= GBEMU_0x2;
        this.checkIRQMatching();
      }
      this.statTracker = 1;
      this.modeSTAT = GBEMU_3;
    }
  }
  scanLineMode0(): void {
    //Horizontal Blanking Period
    if (this.modeSTAT !== 0) {
      if (this.statTracker !== GBEMU_2) {
        if (this.statTracker === 0) {
          if (this.mode2TriggerSTAT) {
            this.interruptsRequested |= GBEMU_0x2;
            this.checkIRQMatching();
          }
          this.modeSTAT = GBEMU_3;
        }
        this.incrementScanLineQueue();
        this.updateSpriteCount(this.actualScanLine);
        this.statTracker = GBEMU_2;
      }
      if (this.lcdTicks >= this.spriteCount) {
        if (this.hdmaRunning) {
          this.executeHDMA();
        }
        if (this.mode0TriggerSTAT) {
          this.interruptsRequested |= GBEMU_0x2;
          this.checkIRQMatching();
        }
        this.statTracker = GBEMU_3;
        this.modeSTAT = 0;
      }
    }
  }
  clocksUntilLYCMatch(): number {
    //debugLog('This is clocksUntilLYCMatch');
    if (this.memory[GBEMU_0xFF45] !== 0) {
      if (this.memory[GBEMU_0xFF45] > this.actualScanLine) {
        return GBEMU_456 * (this.memory[GBEMU_0xFF45] - this.actualScanLine);
      }
      return GBEMU_456 * (GBEMU_154 - this.actualScanLine + this.memory[GBEMU_0xFF45]);
    }
    return GBEMU_456 * (this.actualScanLine === GBEMU_153 && this.memory[GBEMU_0xFF44] === 0 ? GBEMU_154 : GBEMU_153 - this.actualScanLine) + GBEMU_8;
  }
  clocksUntilMode0(): number {
    //debugLog('This is clocksUntilMode0');
    switch (this.modeSTAT) {
      case 0:
        if (this.actualScanLine === GBEMU_143) {
          this.updateSpriteCount(0);
          return this.spriteCount + GBEMU_5016;
        }
        this.updateSpriteCount(this.actualScanLine + 1);
        return this.spriteCount + GBEMU_456;
      case GBEMU_2:
      case GBEMU_3:
        this.updateSpriteCount(this.actualScanLine);
        return this.spriteCount;
      case 1:
        this.updateSpriteCount(0);
        return this.spriteCount + GBEMU_456 * (GBEMU_154 - this.actualScanLine);
      default:
        return 0;
    }
  }
  updateSpriteCount(line: number): void {
    this.spriteCount = GBEMU_252;
    if (this.cGBC && this.gfxSpriteShow) {
      //Is the window enabled and are we in CGB mode?
      let lineAdjusted = line + GBEMU_0x10;
      let yoffset = 0;
      let yCap = this.gfxSpriteNormalHeight ? GBEMU_0x8 : GBEMU_0x10;
      let oamAddress: number = GBEMU_0xFE00;
      while (oamAddress < GBEMU_0xFEA0 && this.spriteCount < GBEMU_312) {
        yoffset = lineAdjusted - this.memory[oamAddress];
        if (yoffset > -1 && yoffset < yCap) {
          this.spriteCount += GBEMU_6;
        }
        oamAddress += GBEMU_4;
      }
    }
  }
  matchLYC(): void {
    //LYC Register Compare
    //debugLog('This is matchLYC');
    if (this.memory[GBEMU_0xFF44] === this.memory[GBEMU_0xFF45]) {
      this.memory[GBEMU_0xFF41] |= GBEMU_0x04;
      if (this.lycMatchTriggerSTAT) {
        this.interruptsRequested |= GBEMU_0x2;
        this.checkIRQMatching();
      }
    } else {
      this.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
    }
  }
  updateCore(): void {
    //debugLog('This is updateCore');
    //Update the clocking for the LCD emulation:
    this.lcdTicks += this.cpuTicks >> this.doubleSpeedShifter; //LCD Timing
    this.lcdControl[this.actualScanLine](this); //Scan Line and STAT Mode Control
    //Single-speed relative timing for A/V emulation:
    let timedTicks = this.cpuTicks >> this.doubleSpeedShifter; //CPU clocking can be updated from the LCD handling.
    this.audioTicks += timedTicks; //Audio Timing
    this.emulatorTicks += timedTicks; //Emulator Timing
    //CPU Timers:
    this.divTicks += this.cpuTicks; //DIV Timing
    if (this.timaEnabled) {
      //TIMA Timing
      this.timerTicks += this.cpuTicks;
      while (this.timerTicks >= this.tacClocker) {
        this.timerTicks -= this.tacClocker;
        this.memory[GBEMU_0xFF05] += 1;
        if (this.memory[GBEMU_0xFF05] === GBEMU_0x100) {
          this.memory[GBEMU_0xFF05] = this.memory[GBEMU_0xFF06];
          this.interruptsRequested |= GBEMU_0x4;
          this.checkIRQMatching();
        }
      }
    }
    if (this.serialTimer > 0) {
      //Serial Timing
      //IRQ Counter:
      this.serialTimer -= this.cpuTicks;
      if (this.serialTimer <= 0) {
        this.interruptsRequested |= GBEMU_0x8;
        this.checkIRQMatching();
      }
      //Bit Shit Counter:
      this.serialShiftTimer -= this.cpuTicks;
      if (this.serialShiftTimer <= 0) {
        this.serialShiftTimer = this.serialShiftTimerAllocated;
        this.memory[GBEMU_0xFF01] = ((this.memory[GBEMU_0xFF01] << 1) & GBEMU_0xFE) | GBEMU_0x01; //We could shift in actual link data here if we were to implement such!!!
      }
    }
  }
  updateCoreFull(): void {
    //debugLog('This is updateCoreFull');
    //Update the state machine:
    this.updateCore();
    //End of iteration routine:
    if (this.emulatorTicks >= this.cpuCyclesTotal) {
      this.iterationEndRoutine();
    }
  }
  initializeLCDController(): void {
    //debugLog('This is initializeLCDController');
    //Display on hanlding:
    let line = 0;
    while (line < GBEMU_154) {
      if (line < GBEMU_143) {
        //We're on a normal scan line:
        this.lineControl[line] = (parentObj: GameBoyCore) => {
          if (parentObj.lcdTicks < GBEMU_80) {
            parentObj.scanLineMode2();
          } else if (parentObj.lcdTicks < GBEMU_252) {
            parentObj.scanLineMode3();
          } else if (parentObj.lcdTicks < GBEMU_456) {
            parentObj.scanLineMode0();
          } else {
            //We're on a new scan line:
            parentObj.lcdTicks -= GBEMU_456;
            if (parentObj.statTracker !== GBEMU_3) {
              //Make sure the mode 0 handler was run at least once per scan line:
              if (parentObj.statTracker !== GBEMU_2) {
                if (parentObj.statTracker === 0 && parentObj.mode2TriggerSTAT) {
                  parentObj.interruptsRequested |= GBEMU_0x2;
                }
                parentObj.incrementScanLineQueue();
              }
              if (parentObj.hdmaRunning) {
                parentObj.executeHDMA();
              }
              if (parentObj.mode0TriggerSTAT) {
                parentObj.interruptsRequested |= GBEMU_0x2;
              }
            }
            //Update the scanline registers and assert the LYC counter:
            parentObj.memory[GBEMU_0xFF44] += 1;
            parentObj.actualScanLine = parentObj.memory[GBEMU_0xFF44];
            //Perform a LYC counter assert:
            if (parentObj.actualScanLine === parentObj.memory[GBEMU_0xFF45]) {
              parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
              if (parentObj.lycMatchTriggerSTAT) {
                parentObj.interruptsRequested |= GBEMU_0x2;
              }
            } else {
              parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
            }
            parentObj.checkIRQMatching();
            //Reset our mode contingency variables:
            parentObj.statTracker = 0;
            parentObj.modeSTAT = GBEMU_2;
            parentObj.lineControl[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control.
          }
        };
      } else if (line === GBEMU_143) {
        //We're on the last visible scan line of the LCD screen:
        this.lineControl[GBEMU_143] = (parentObj: GameBoyCore) => {
          if (parentObj.lcdTicks < GBEMU_80) {
            parentObj.scanLineMode2();
          } else if (parentObj.lcdTicks < GBEMU_252) {
            parentObj.scanLineMode3();
          } else if (parentObj.lcdTicks < GBEMU_456) {
            parentObj.scanLineMode0();
          } else {
            //Starting V-Blank:
            //Just finished the last visible scan line:
            parentObj.lcdTicks -= GBEMU_456;
            if (parentObj.statTracker !== GBEMU_3) {
              //Make sure the mode 0 handler was run at least once per scan line:
              if (parentObj.statTracker !== GBEMU_2) {
                if (parentObj.statTracker === 0 && parentObj.mode2TriggerSTAT) {
                  parentObj.interruptsRequested |= GBEMU_0x2;
                }
                parentObj.incrementScanLineQueue();
              }
              if (parentObj.hdmaRunning) {
                parentObj.executeHDMA();
              }
              if (parentObj.mode0TriggerSTAT) {
                parentObj.interruptsRequested |= GBEMU_0x2;
              }
            }
            //Update the scanline registers and assert the LYC counter:
            parentObj.actualScanLine = GBEMU_144;
            parentObj.memory[GBEMU_0xFF44] = GBEMU_144;
            //Perform a LYC counter assert:
            if (parentObj.memory[GBEMU_0xFF45] === GBEMU_144) {
              parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
              if (parentObj.lycMatchTriggerSTAT) {
                parentObj.interruptsRequested |= GBEMU_0x2;
              }
            } else {
              parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
            }
            //Reset our mode contingency variables:
            parentObj.statTracker = 0;
            //Update our state for v-blank:
            parentObj.modeSTAT = 1;
            parentObj.interruptsRequested |= parentObj.mode1TriggerSTAT ? GBEMU_0x3 : GBEMU_0x1;
            parentObj.checkIRQMatching();
            //Attempt to blit out to our canvas:
            if (parentObj.drewBlank === 0) {
              //Ensure JIT framing alignment:
              if (parentObj.totalLinesPassed < GBEMU_144 || (parentObj.totalLinesPassed === GBEMU_144 && parentObj.midScanlineOffset > -1)) {
                //Make sure our gfx are up-to-date:
                parentObj.graphicsJITVBlank();
                //Draw the frame:
                parentObj.prepareFrame();
              }
            } else {
              //LCD off takes at least GBEMU_2 frames:
              parentObj.drewBlank -= 1;
            }
            parentObj.lineControl[GBEMU_144](parentObj); //Scan Line and STAT Mode Control.
          }
        };
      } else if (line < GBEMU_153) {
        //In VBlank
        this.lineControl[line] = (parentObj: GameBoyCore) => {
          if (parentObj.lcdTicks >= GBEMU_456) {
            //We're on a new scan line:
            parentObj.lcdTicks -= GBEMU_456;
            parentObj.memory[GBEMU_0xFF44] += 1;
            parentObj.actualScanLine = parentObj.memory[GBEMU_0xFF44];
            //Perform a LYC counter assert:
            if (parentObj.actualScanLine === parentObj.memory[GBEMU_0xFF45]) {
              parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
              if (parentObj.lycMatchTriggerSTAT) {
                parentObj.interruptsRequested |= GBEMU_0x2;
                parentObj.checkIRQMatching();
              }
            } else {
              parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
            }
            parentObj.lineControl[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control.
          }
        };
      } else {
        //VBlank Ending (We're on the last actual scan line)
        this.lineControl[GBEMU_153] = (parentObj: GameBoyCore) => {
          if (parentObj.lcdTicks >= GBEMU_8) {
            if (parentObj.statTracker !== GBEMU_4 && parentObj.memory[GBEMU_0xFF44] === GBEMU_153) {
              parentObj.memory[GBEMU_0xFF44] = 0; //LY register resets to 0 early.
              //Perform a LYC counter assert:
              if (parentObj.memory[GBEMU_0xFF45] === 0) {
                parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
                if (parentObj.lycMatchTriggerSTAT) {
                  parentObj.interruptsRequested |= GBEMU_0x2;
                  parentObj.checkIRQMatching();
                }
              } else {
                parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
              }
              parentObj.statTracker = GBEMU_4;
            }
            if (parentObj.lcdTicks >= GBEMU_456) {
              //We reset back to the beginning:
              parentObj.lcdTicks -= GBEMU_456;
              parentObj.statTracker = 0;
              parentObj.actualScanLine = 0;
              parentObj.lineControl[0](parentObj); //Scan Line and STAT Mode Control.
            }
          }
        };
      }
      line += 1;
    }
  }
  displayShowOff(): void {
    //debugLog('This is DisplayShowOff')
    if (this.drewBlank === 0) {
      //Output a blank screen to the output framebuffer:
      this.clearFrameBuffer();
      this.drewFrame = true;
    }
    this.drewBlank = GBEMU_2;
  }
  executeHDMA(): void {
    this.dMAWrite(1);
    if (this.halt) {
      if (this.lcdTicks - this.spriteCount < ((GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20)) {
        //HALT clocking correction:
        this.cpuTicks = GBEMU_4 + ((GBEMU_0x20 + this.spriteCount) << this.doubleSpeedShifter);
        this.lcdTicks = this.spriteCount + ((GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20);
      }
    } else {
      this.lcdTicks += (GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20; //LCD Timing Update For HDMA.
    }
    if (this.memory[GBEMU_0xFF55] === 0) {
      this.hdmaRunning = false;
      this.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed ('Hidden last step,' since some roms don't imply this, but most do).
    } else {
      this.memory[GBEMU_0xFF55] -= 1;
    }
  }
  clockUpdate(): void {
    //debugLog('This is clockUpdate');
    if (this.cTimeR) {
      let dateObj = new NewDate(); // The line is changed for benchmarking.
      let newTime = dateObj.getTime();
      let timeElapsed = newTime - this.lastIteration; //Get the numnber of milliseconds since this last executed.
      this.lastIteration = newTime;
      if (this.cTimeR && !this.rtcHalt) {
        //Update the MBC3 RTC:
        this.rtcSeconds += timeElapsed / GBEMU_1000;
        while (this.rtcSeconds >= GBEMU_60) {
          //System can stutter, so the seconds difference can get large, thus the 'while'.
          this.rtcSeconds -= GBEMU_60;
          this.rtcMinutes += 1;
          if (this.rtcMinutes >= GBEMU_60) {
            this.rtcMinutes -= GBEMU_60;
            this.rtcHours += 1;
            if (this.rtcHours >= GBEMU_24) {
              this.rtcHours -= GBEMU_24;
              this.rtcDays += 1;
              if (this.rtcDays >= GBEMU_512) {
                this.rtcDays -= GBEMU_512;
                this.rtcDayOverFlow = true;
              }
            }
          }
        }
      }
    }
  }
  prepareFrame(): void {
    //debugLog('This is prepareFrame');
    //Copy the internal frame buffer to the output buffer:
    this.swizzleFrameBuffer();
    this.drewFrame = true;
  }
  requestDraw(): void {
    //debugLog('This is requestDraw');
    if (this.drewFrame) {
      this.dispatchDraw();
    }
  }
  dispatchDraw(): void {
    //debugLog('This is dispatchDraw');
    let canvasRGBALength = this.offscreenRGBCount;
    if (canvasRGBALength > 0) {
      //We actually updated the graphics internally, so copy out:
      let frameBuffer = canvasRGBALength === GBEMU_92160 ? this.swizzledFrame : this.resizeFrameBuffer();
      let canvasData = this.canvasBuffer!.data;
      let bufferIndex = 0;
      let canvasIndex = 0;
      while (canvasIndex < canvasRGBALength) {
        canvasData[canvasIndex++] = (frameBuffer as TNextArray)[bufferIndex++];
        canvasData[canvasIndex++] = (frameBuffer as TNextArray)[bufferIndex++];
        canvasData[canvasIndex++] = (frameBuffer as TNextArray)[bufferIndex++];
        canvasIndex += 1;
      }
      this.graphicsBlit();
    }
  }
  swizzleFrameBuffer(): void {
    //debugLog('This is swizzleFrameBuffer');
    //Convert our dirty GBEMU_24-bit (GBEMU_24-bit, with internal render flags above it) framebuffer to an GBEMU_8-bit buffer with separate indices for the RGB channels:
    let frameBuffer = this.frameBuffer;
    let bufferIndex = 0;
    let canvasIndex: number = 0;
    while (canvasIndex < GBEMU_69120) {
      (this.swizzledFrame as TNextArray)[canvasIndex++] = (frameBuffer[bufferIndex] >> GBEMU_16) & GBEMU_0xFF; //Red
      (this.swizzledFrame as TNextArray)[canvasIndex++] = (frameBuffer[bufferIndex] >> GBEMU_8) & GBEMU_0xFF; //Green
      (this.swizzledFrame as TNextArray)[canvasIndex++] = frameBuffer[bufferIndex++] & GBEMU_0xFF; //Blue
    }
  }
  clearFrameBuffer(): void {
    //debugLog('This is clearFrameBuffer');
    let bufferIndex = 0;
    if (this.cGBC || this.colorizedGBPalettes) {
      while (bufferIndex < GBEMU_69120) {
        this.swizzledFrame![bufferIndex++] = GBEMU_248;
      }
    } else {
      while (bufferIndex < GBEMU_69120) {
        this.swizzledFrame![bufferIndex++] = GBEMU_239;
        this.swizzledFrame![bufferIndex++] = GBEMU_255;
        this.swizzledFrame![bufferIndex++] = GBEMU_222;
      }
    }
  }
  resizeFrameBuffer(): TNextArray {
    //debugLog('This is resizeFrameBuffer');
    //Return a reference to the generated resized framebuffer:
    return this.resizer!.resize(this.swizzledFrame as Float32Array | Uint8Array);
  }
  compileResizeFrameBufferFunction(): void {
    //debugLog('This is compileResizeFrameBufferFunction');
    if (this.offscreenRGBCount > 0) {
      this.resizer = new Resize(GBEMU_160, GBEMU_144, this.offscreenWidth, this.offscreenHeight, false, true);
    }
  }
  renderScanLine(scanlineToRender: number): void {
    this.pixelStart = scanlineToRender * GBEMU_160;
    if (this.bgEnabled) {
      this.pixelEnd = 160;
      this.bgLayerRender!(scanlineToRender);
      this.windowLayerRender!(scanlineToRender);
    } else {
      let pixelLine = (scanlineToRender + 1) * GBEMU_160;
      let defaultColor = this.cGBC || this.colorizedGBPalettes ? GBEMU_0xF8F8F8 : GBEMU_0xEFFFDE;
      let pixelPosition: number = scanlineToRender * GBEMU_160 + this.currentX;
      while (pixelPosition < pixelLine) {
        this.frameBuffer[pixelPosition] = defaultColor;
        pixelPosition += 1;
      }
    }
    this.spriteLayerRender!(scanlineToRender);
    this.currentX = 0;
    this.midScanlineOffset = -1;
  }
  renderMidScanLine(): void {
    if (this.actualScanLine < GBEMU_144 && this.modeSTAT === GBEMU_3) {
      //TODO: Get this accurate:
      if (this.midScanlineOffset === -1) {
        this.midScanlineOffset = this.backgroundX & GBEMU_0x7;
      }
      if (this.lcdTicks >= GBEMU_82) {
        this.pixelEnd = this.lcdTicks - GBEMU_74;
        this.pixelEnd = Math.min(this.pixelEnd - this.midScanlineOffset - (this.pixelEnd % GBEMU_0x8), GBEMU_160);
        if (this.bgEnabled) {
          this.pixelStart = this.lastUnrenderedLine * GBEMU_160;
          this.bgLayerRender!(this.lastUnrenderedLine);
          this.windowLayerRender!(this.lastUnrenderedLine);
          //TODO: Do midscanline JIT for sprites...
        } else {
          let pixelLine = this.lastUnrenderedLine * GBEMU_160 + this.pixelEnd;
          let defaultColor = this.cGBC || this.colorizedGBPalettes ? GBEMU_0xF8F8F8 : GBEMU_0xEFFFDE;
          let pixelPosition: number = this.lastUnrenderedLine * GBEMU_160 + this.currentX;
          while (pixelPosition < pixelLine) {
            this.frameBuffer[pixelPosition] = defaultColor;
            pixelPosition += 1;
          }
        }
        this.currentX = this.pixelEnd;
      }
    }
  }
  initializeModeSpecificArrays(): void {
    //debugLog('This is initializeModeSpecificArrays');
    this.lcdControl = this.lcdIsOn ? this.lineControl : this.disPlayOffControl;
    if (this.cGBC) {
      this.gbcOBJRawPalette = this.getTypedArray(GBEMU_0x40, 0, 'uint8');
      this.gbcBGRawPalette = this.getTypedArray(GBEMU_0x40, 0, 'uint8');
      this.gbcOBJPalette = this.getTypedArray(GBEMU_0x20, GBEMU_0x1000000, 'int32');
      this.gbcBGPalette = this.getTypedArray(GBEMU_0x40, 0, 'int32');
      this.bgCHRBank2.array = this.getTypedArray(GBEMU_0x800, 0, 'uint8');
      this.bgCHRCurrentBank = this.currvramBank > 0 ? this.bgCHRBank2 : this.bgCHRBank1;
      this.tileCache = this.generateCacheArray(GBEMU_0xf80);
    } else {
      this.gbOBJPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
      this.gbBGPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
      this.bgPalette = this.gbBGPalette;
      this.objPalette = this.gbOBJPalette;
      this.tileCache = this.generateCacheArray(GBEMU_0x700);
      this.sortBuffer = this.getTypedArray(GBEMU_0x100, 0, 'uint8');
      this.oamAddressCache = this.getTypedArray(GBEMU_10, 0, 'int32');
    }
    this.renderPathBuild();
  }
  gBCtoGBModeAdjust(): void {
    //debugLog('This is GBCtoGBModeAdjust');
    cout('Stepping down from GBC mode.', 0);
    this.bgCHRBank2.array = new Int32Array();
    this.vram = new Int32Array();
    this.gbcMemory = new Int32Array();
    this.bgCHRCurrentBank!.array = new Int32Array();
    this.tileCache!.length = GBEMU_0x700;
    if (settings[GBEMU_4]) {
      this.gbBGColorizedPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
      this.gbOBJColorizedPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
      this.cachedBGPaletteConversion = this.getTypedArray(GBEMU_4, 0, 'int32');
      this.cachedOBJPaletteConversion = this.getTypedArray(GBEMU_8, 0, 'int32');
      this.bgPalette = this.gbBGColorizedPalette;
      this.objPalette = this.gbOBJColorizedPalette;
      this.gbOBJPalette = null;
      this.gbBGPalette = null;
      this.getGBCColor();
    } else {
      this.gbOBJPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
      this.gbBGPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
      this.bgPalette = this.gbBGPalette;
      this.objPalette = this.gbOBJPalette;
    }
    this.sortBuffer = this.getTypedArray(GBEMU_0x100, 0, 'uint8');
    this.oamAddressCache = this.getTypedArray(GBEMU_10, 0, 'int32');
    this.renderPathBuild();
    this.memoryReadJumpCompile();
    this.memoryWriteJumpCompile();
  }
  renderPathBuild(): void {
    //debugLog('This is renderPathBuild');
    if (!this.cGBC) {
      this.bgLayerRender = this.bGGBLayerRender;
      this.windowLayerRender = this.windowGBLayerRender;
      this.spriteLayerRender = this.spriteGBLayerRender;
    } else {
      this.priorityFlaggingPathRebuild();
      this.spriteLayerRender = this.spriteGBCLayerRender;
    }
  }
  priorityFlaggingPathRebuild(): void {
    //debugLog('This is priorityFlaggingPathRebuild');
    if (this.bgPriorityEnabled) {
      this.bgLayerRender = this.bGGBCLayerRender;
      this.windowLayerRender = this.windowGBCLayerRender;
    } else {
      this.bgLayerRender = this.bGGBCLayerRenderNoPriorityFlagging;
      this.windowLayerRender = this.windowGBCLayerRenderNoPriorityFlagging;
    }
  }
  rGBTint(value: number): number {
    //Adjustment for the GBC's tinting (According to Gambatte):
    let r = value & GBEMU_0x1f;
    let g = (value >> GBEMU_5) & GBEMU_0x1f;
    let b = (value >> GBEMU_10) & GBEMU_0x1f;
    return (((r * GBEMU_13 + g * GBEMU_2 + b) >> 1) << GBEMU_16) | ((g * GBEMU_3 + b) << GBEMU_9) | ((r * GBEMU_3 + g * GBEMU_2 + b * GBEMU_11) >> 1);
  }
  getGBCColor(): void {
    //debugLog('This is getGBCColor');
    //GBC Colorization of DMG roms:
    //BG
    let counter: number = 0;
    while (counter < GBEMU_4) {
      let adjustedIndex = counter << 1;
      //BG
      this.cachedBGPaletteConversion![counter] = this.rGBTint((this.gbcBGRawPalette![adjustedIndex | 1] << GBEMU_8) | this.gbcBGRawPalette![adjustedIndex]);
      //OBJ 1
      this.cachedOBJPaletteConversion![counter] = this.rGBTint((this.gbcOBJRawPalette![adjustedIndex | 1] << GBEMU_8) | this.gbcOBJRawPalette![adjustedIndex]);
      counter += 1;
    }
    //OBJ GBEMU_2
    counter = GBEMU_4;
    while (counter < GBEMU_8) {
      let adjustedIndex = counter << 1;
      this.cachedOBJPaletteConversion![counter] = this.rGBTint((this.gbcOBJRawPalette![adjustedIndex | 1] << GBEMU_8) | this.gbcOBJRawPalette![adjustedIndex]);
      counter += 1;
    }
    //Update the palette entries:
    this.updateGBBGPalette = this.updateGBColorizedBGPalette;
    this.updateGBOBJPalette = this.updateGBColorizedOBJPalette;
    this.updateGBBGPalette(this.memory[GBEMU_0xFF47]);
    this.updateGBOBJPalette(0, this.memory[GBEMU_0xFF48]);
    this.updateGBOBJPalette(1, this.memory[GBEMU_0xFF49]);
    this.colorizedGBPalettes = true;
  }
  updateGBRegularBGPalette(data: number): void {
    //debugLog('This is updateGBRegularBGPalette');
    this.gbBGPalette![0] = this.colors[data & GBEMU_0x03] | GBEMU_0x2000000;
    this.gbBGPalette![1] = this.colors[(data >> GBEMU_2) & GBEMU_0x03];
    this.gbBGPalette![GBEMU_2] = this.colors[(data >> GBEMU_4) & GBEMU_0x03];
    this.gbBGPalette![GBEMU_3] = this.colors[data >> GBEMU_6];
  }
  updateGBColorizedBGPalette(data: number): void {
    //debugLog('This is updateGBColorizedBGPalette');
    //GB colorization:
    this.gbBGColorizedPalette![0] = this.cachedBGPaletteConversion![data & GBEMU_0x03] | GBEMU_0x2000000;
    this.gbBGColorizedPalette![1] = this.cachedBGPaletteConversion![(data >> GBEMU_2) & GBEMU_0x03];
    this.gbBGColorizedPalette![GBEMU_2] = this.cachedBGPaletteConversion![(data >> GBEMU_4) & GBEMU_0x03];
    this.gbBGColorizedPalette![GBEMU_3] = this.cachedBGPaletteConversion![data >> GBEMU_6];
  }
  updateGBRegularOBJPalette(index: number, data: number): void {
    //debugLog('This is updateGBRegularOBJPalette');
    this.gbOBJPalette![index | 1] = this.colors[(data >> GBEMU_2) & GBEMU_0x03];
    this.gbOBJPalette![index | GBEMU_2] = this.colors[(data >> GBEMU_4) & GBEMU_0x03];
    this.gbOBJPalette![index | GBEMU_3] = this.colors[data >> GBEMU_6];
  }
  updateGBColorizedOBJPalette(index: number, data: number): void {
    //debugLog('This is updateGBColorizedOBJPalette');
    //GB colorization:
    this.gbOBJColorizedPalette![index | 1] = this.cachedOBJPaletteConversion![index | ((data >> GBEMU_2) & GBEMU_0x03)];
    this.gbOBJColorizedPalette![index | GBEMU_2] = this.cachedOBJPaletteConversion![index | ((data >> GBEMU_4) & GBEMU_0x03)];
    this.gbOBJColorizedPalette![index | GBEMU_3] = this.cachedOBJPaletteConversion![index | (data >> GBEMU_6)];
  }
  updateGBCBGPalette(indexTemp: number, dataTemp: number): void {
    let index = indexTemp;
    let data = dataTemp;
    if (this.gbcBGRawPalette![index] !== data) {
      this.midScanLineJIT();
      //Update the color palette for BG tiles since it changed:
      this.gbcBGRawPalette![index] = data;
      if ((index & GBEMU_0x06) === 0) {
        //Palette 0 (Special tile Priority stuff)
        data = GBEMU_0x2000000 | this.rGBTint((this.gbcBGRawPalette![index | 1] << GBEMU_8) | this.gbcBGRawPalette![index & GBEMU_0x3E]);
        index >>= 1;
        this.gbcBGPalette![index] = data;
        this.gbcBGPalette![GBEMU_0x20 | index] = GBEMU_0x1000000 | data;
      } else {
        //Regular Palettes (No special crap)
        data = this.rGBTint((this.gbcBGRawPalette![index | 1] << GBEMU_8) | this.gbcBGRawPalette![index & GBEMU_0x3E]);
        index >>= 1;
        this.gbcBGPalette![index] = data;
        this.gbcBGPalette![GBEMU_0x20 | index] = GBEMU_0x1000000 | data;
      }
    }
  }
  updateGBCOBJPalette(index: number, data: number): void {
    if (this.gbcOBJRawPalette![index] !== data) {
      //Update the color palette for OBJ tiles since it changed:
      this.gbcOBJRawPalette![index] = data;
      if ((index & GBEMU_0x06) > 0) {
        //Regular Palettes (No special crap)
        this.midScanLineJIT();
        this.gbcOBJPalette![index >> 1] =
          GBEMU_0x1000000 | this.rGBTint((this.gbcOBJRawPalette![index | 1] << GBEMU_8) | this.gbcOBJRawPalette![index & GBEMU_0x3E]);
      }
    }
  }
  bGGBLayerRender(scanlineToRender: number): void {
    //debugLog('This is BGGBLayerRender');
    let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
    let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
    let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles  we're fetching from.
    let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
    let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
    let pixelPositionEnd =
      this.pixelStart +
      (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
    let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
    let chrCode = this.bgCHRBank1.array[tileNumber];
    if (chrCode < this.gfxBackgroundBankOffset) {
      chrCode |= GBEMU_0x100;
    }
    let tile = this.tileCache![chrCode].array;
    let texel: number = scrollXAdjusted & GBEMU_0x7;
    while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[tileYLine | texel++]];
      scrollXAdjusted += 1;
    }
    let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
    scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
    scrollXAdjustedAligned += tileNumber;
    while (tileNumber < scrollXAdjustedAligned) {
      tileNumber += 1;
      chrCode = this.bgCHRBank1.array[tileNumber];
      if (chrCode < this.gfxBackgroundBankOffset) {
        chrCode |= GBEMU_0x100;
      }
      tile = this.tileCache![chrCode].array;
      let texel = tileYLine;
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel]];
    }
    if (pixelPosition < pixelPositionEnd) {
      if (scrollXAdjusted < GBEMU_0x100) {
        tileNumber += 1;
        chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        tile = this.tileCache![chrCode].array;
        let texel: number = tileYLine - 1;
        while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
          texel += 1;
          this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel]];
          scrollXAdjusted += 1;
        }
      }
      scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
      while (tileYDown < scrollXAdjustedAligned) {
        chrCode = this.bgCHRBank1.array[tileYDown++];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        tile = this.tileCache![chrCode].array;
        let texel = tileYLine;
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel]];
      }
      if (pixelPosition < pixelPositionEnd) {
        chrCode = this.bgCHRBank1.array[tileYDown];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        tile = this.tileCache![chrCode].array;
        switch (pixelPositionEnd - pixelPosition) {
          case GBEMU_7:
            this.frameBuffer![pixelPosition + GBEMU_6] = this.bgPalette![tile[tileYLine | GBEMU_6]];
          case GBEMU_6:
            this.frameBuffer![pixelPosition + GBEMU_5] = this.bgPalette![tile[tileYLine | GBEMU_5]];
          case GBEMU_5:
            this.frameBuffer![pixelPosition + GBEMU_4] = this.bgPalette![tile[tileYLine | GBEMU_4]];
          case GBEMU_4:
            this.frameBuffer![pixelPosition + GBEMU_3] = this.bgPalette![tile[tileYLine | GBEMU_3]];
          case GBEMU_3:
            this.frameBuffer![pixelPosition + GBEMU_2] = this.bgPalette![tile[tileYLine | GBEMU_2]];
          case GBEMU_2:
            this.frameBuffer![pixelPosition + 1] = this.bgPalette![tile[tileYLine | 1]];
          case 1:
            this.frameBuffer![pixelPosition] = this.bgPalette![tile[tileYLine]];
          default:
            break;
        }
      }
    }
  }
  bGGBCLayerRender(scanlineToRender: number): void {
    let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
    let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
    let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles   we're fetching from.
    let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
    let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
    let pixelPositionEnd =
      this.pixelStart +
      (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
    let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
    let chrCode = this.bgCHRBank1.array[tileNumber];
    if (chrCode < this.gfxBackgroundBankOffset) {
      chrCode |= GBEMU_0x100;
    }
    let attrCode = this.bgCHRBank2.array[tileNumber];
    let tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
    let palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
    let texel: number = scrollXAdjusted & GBEMU_0x7;
    while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[tileYLine | texel++]];
      scrollXAdjusted += 1;
    }
    let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
    scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
    scrollXAdjustedAligned += tileNumber;
    while (tileNumber < scrollXAdjustedAligned) {
      tileNumber += 1;
      chrCode = this.bgCHRBank1.array[tileNumber];
      if (chrCode < this.gfxBackgroundBankOffset) {
        chrCode |= GBEMU_0x100;
      }
      attrCode = this.bgCHRBank2.array[tileNumber];
      tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
      palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
      let texel = tileYLine;
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
    }
    if (pixelPosition < pixelPositionEnd) {
      if (scrollXAdjusted < GBEMU_0x100) {
        tileNumber += 1;
        chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileNumber];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
        texel = tileYLine - 1;
        while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
          texel += 1;
          this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
          scrollXAdjusted += 1;
        }
      }
      scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
      while (tileYDown < scrollXAdjustedAligned) {
        chrCode = this.bgCHRBank1.array[tileYDown];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileYDown++];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
        let texel = tileYLine;
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
      }
      if (pixelPosition < pixelPositionEnd) {
        chrCode = this.bgCHRBank1.array[tileYDown];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileYDown];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
        switch (pixelPositionEnd - pixelPosition) {
          case GBEMU_7:
            this.frameBuffer![pixelPosition + GBEMU_6] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_6]];
          case GBEMU_6:
            this.frameBuffer![pixelPosition + GBEMU_5] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_5]];
          case GBEMU_5:
            this.frameBuffer![pixelPosition + GBEMU_4] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_4]];
          case GBEMU_4:
            this.frameBuffer![pixelPosition + GBEMU_3] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_3]];
          case GBEMU_3:
            this.frameBuffer![pixelPosition + GBEMU_2] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_2]];
          case GBEMU_2:
            this.frameBuffer![pixelPosition + 1] = this.gbcBGPalette![palette | tile[tileYLine | 1]];
          case 1:
            this.frameBuffer![pixelPosition] = this.gbcBGPalette![palette | tile[tileYLine]];
          default:
            break;
        }
      }
    }
  }
  bGGBCLayerRenderNoPriorityFlagging(scanlineToRender: number): void {
    //debugLog('This is BGGBCLayerRenderNoPriorityFlagging');
    let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
    let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
    let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles   // we're fetching from.
    let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
    let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
    let pixelPositionEnd =
      this.pixelStart +
      (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
    let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
    let chrCode = this.bgCHRBank1.array[tileNumber];
    if (chrCode < this.gfxBackgroundBankOffset) {
      chrCode |= GBEMU_0x100;
    }
    let attrCode = this.bgCHRBank2.array[tileNumber];
    let tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
    let palette = (attrCode & GBEMU_0x7) << GBEMU_2;
    let texel: number = scrollXAdjusted & GBEMU_0x7;
    while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[tileYLine | texel++]];
      scrollXAdjusted += 1;
    }
    let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
    scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
    scrollXAdjustedAligned += tileNumber;
    while (tileNumber < scrollXAdjustedAligned) {
      tileNumber += 1;
      chrCode = this.bgCHRBank1.array[tileNumber];
      if (chrCode < this.gfxBackgroundBankOffset) {
        chrCode |= GBEMU_0x100;
      }
      attrCode = this.bgCHRBank2.array[tileNumber];
      tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
      palette = (attrCode & GBEMU_0x7) << GBEMU_2;
      let texel = tileYLine;
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
      this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
    }
    if (pixelPosition < pixelPositionEnd) {
      if (scrollXAdjusted < GBEMU_0x100) {
        tileNumber += 1;
        chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileNumber];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = (attrCode & GBEMU_0x7) << GBEMU_2;
        let texel = tileYLine - 1;
        while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
          texel += 1;
          this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
          scrollXAdjusted += 1;
        }
      }
      scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
      while (tileYDown < scrollXAdjustedAligned) {
        chrCode = this.bgCHRBank1.array[tileYDown];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileYDown++];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = (attrCode & GBEMU_0x7) << GBEMU_2;
        let texel = tileYLine;
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
        this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
      }
      if (pixelPosition < pixelPositionEnd) {
        chrCode = this.bgCHRBank1.array[tileYDown];
        if (chrCode < this.gfxBackgroundBankOffset) {
          chrCode |= GBEMU_0x100;
        }
        attrCode = this.bgCHRBank2.array[tileYDown];
        tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        palette = (attrCode & GBEMU_0x7) << GBEMU_2;
        switch (pixelPositionEnd - pixelPosition) {
          case GBEMU_7:
            this.frameBuffer![pixelPosition + GBEMU_6] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_6]];
          case GBEMU_6:
            this.frameBuffer![pixelPosition + GBEMU_5] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_5]];
          case GBEMU_5:
            this.frameBuffer![pixelPosition + GBEMU_4] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_4]];
          case GBEMU_4:
            this.frameBuffer![pixelPosition + GBEMU_3] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_3]];
          case GBEMU_3:
            this.frameBuffer![pixelPosition + GBEMU_2] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_2]];
          case GBEMU_2:
            this.frameBuffer![pixelPosition + 1] = this.gbcBGPalette![palette | tile[tileYLine | 1]];
          case 1:
            this.frameBuffer![pixelPosition] = this.gbcBGPalette![palette | tile[tileYLine]];
          default:
            break;
        }
      }
    }
  }
  windowGBLayerRender(scanlineToRender: number): void {
    //debugLog('This is WindowGBLayerRender');
    if (this.gfxWindowDisplay) {
      //Is the window enabled?
      let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
      if (scrollYAdjusted >= 0) {
        let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
        let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
        let pixelPositionEnd = this.pixelStart + this.pixelEnd;
        if (pixelPosition < pixelPositionEnd) {
          let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
          let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
          let chrCode = this.bgCHRBank1.array[tileNumber];
          if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
          }
          let tile = this.tileCache![chrCode].array;
          let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
          scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
          while (texel < scrollXRangeAdjusted) {
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[tileYLine | texel++]];
          }
          scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
          while (tileNumber < scrollXRangeAdjusted) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
            tile = this.tileCache![chrCode].array;
            texel = tileYLine;
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.bgPalette![tile[texel]];
          }
          if (pixelPosition < pixelPositionEnd) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
              chrCode |= GBEMU_0x100;
            }
            tile = this.tileCache![chrCode].array;
            switch (pixelPositionEnd - pixelPosition) {
              case GBEMU_7:
                this.frameBuffer![pixelPosition + GBEMU_6] = this.bgPalette![tile[tileYLine | GBEMU_6]];
              case GBEMU_6:
                this.frameBuffer![pixelPosition + GBEMU_5] = this.bgPalette![tile[tileYLine | GBEMU_5]];
              case GBEMU_5:
                this.frameBuffer![pixelPosition + GBEMU_4] = this.bgPalette![tile[tileYLine | GBEMU_4]];
              case GBEMU_4:
                this.frameBuffer![pixelPosition + GBEMU_3] = this.bgPalette![tile[tileYLine | GBEMU_3]];
              case GBEMU_3:
                this.frameBuffer![pixelPosition + GBEMU_2] = this.bgPalette![tile[tileYLine | GBEMU_2]];
              case GBEMU_2:
                this.frameBuffer![pixelPosition + 1] = this.bgPalette![tile[tileYLine | 1]];
              case 1:
                this.frameBuffer![pixelPosition] = this.bgPalette![tile[tileYLine]];
              default:
                break;
            }
          }
        }
      }
    }
  }
  windowGBCLayerRender(scanlineToRender: number): void {
    if (this.gfxWindowDisplay) {
      //Is the window enabled?
      let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
      if (scrollYAdjusted >= 0) {
        let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
        let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
        let pixelPositionEnd = this.pixelStart + this.pixelEnd;
        if (pixelPosition < pixelPositionEnd) {
          let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
          let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
          let chrCode = this.bgCHRBank1.array[tileNumber];
          if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
          }
          let attrCode = this.bgCHRBank2.array[tileNumber];
          let tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
          let palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
          let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
          scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
          while (texel < scrollXRangeAdjusted) {
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[tileYLine | texel++]];
          }
          scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
          while (tileNumber < scrollXRangeAdjusted) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
            texel = tileYLine;
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
          }
          if (pixelPosition < pixelPositionEnd) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
              chrCode |= GBEMU_0x100;
            }
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
            switch (pixelPositionEnd - pixelPosition) {
              case GBEMU_7:
                this.frameBuffer![pixelPosition + GBEMU_6] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_6]];
              case GBEMU_6:
                this.frameBuffer![pixelPosition + GBEMU_5] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_5]];
              case GBEMU_5:
                this.frameBuffer![pixelPosition + GBEMU_4] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_4]];
              case GBEMU_4:
                this.frameBuffer![pixelPosition + GBEMU_3] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_3]];
              case GBEMU_3:
                this.frameBuffer![pixelPosition + GBEMU_2] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_2]];
              case GBEMU_2:
                this.frameBuffer![pixelPosition + 1] = this.gbcBGPalette![palette | tile[tileYLine | 1]];
              case 1:
                this.frameBuffer![pixelPosition] = this.gbcBGPalette![palette | tile[tileYLine]];
              default:
                break;
            }
          }
        }
      }
    }
  }
  windowGBCLayerRenderNoPriorityFlagging(scanlineToRender: number): void {
    //debugLog('This is WindowGBCLayerRenderNoPriorityFlagging');
    if (this.gfxWindowDisplay) {
      let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
      if (scrollYAdjusted >= 0) {
        let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
        let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
        let pixelPositionEnd = this.pixelStart + this.pixelEnd;
        if (pixelPosition < pixelPositionEnd) {
          let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
          let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
          let chrCode = this.bgCHRBank1.array[tileNumber];
          if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
          }
          let attrCode = this.bgCHRBank2.array[tileNumber];
          let tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
          let palette = (attrCode & GBEMU_0x7) << GBEMU_2;
          let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
          scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
          while (texel < scrollXRangeAdjusted) {
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[tileYLine | texel++]];
          }
          scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
          while (tileNumber < scrollXRangeAdjusted) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = (attrCode & GBEMU_0x7) << GBEMU_2;
            texel = tileYLine;
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel++]];
            this.frameBuffer![pixelPosition++] = this.gbcBGPalette![palette | tile[texel]];
          }
          if (pixelPosition < pixelPositionEnd) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
              chrCode |= GBEMU_0x100;
            }
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = (attrCode & GBEMU_0x7) << GBEMU_2;
            switch (pixelPositionEnd - pixelPosition) {
              case GBEMU_7:
                this.frameBuffer![pixelPosition + GBEMU_6] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_6]];
              case GBEMU_6:
                this.frameBuffer![pixelPosition + GBEMU_5] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_5]];
              case GBEMU_5:
                this.frameBuffer![pixelPosition + GBEMU_4] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_4]];
              case GBEMU_4:
                this.frameBuffer![pixelPosition + GBEMU_3] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_3]];
              case GBEMU_3:
                this.frameBuffer![pixelPosition + GBEMU_2] = this.gbcBGPalette![palette | tile[tileYLine | GBEMU_2]];
              case GBEMU_2:
                this.frameBuffer![pixelPosition + 1] = this.gbcBGPalette![palette | tile[tileYLine | 1]];
              case 1:
                this.frameBuffer![pixelPosition] = this.gbcBGPalette![palette | tile[tileYLine]];
              default:
                break;
            }
          }
        }
      }
    }
  }
  spriteGBLayerRender(scanlineToRender: number): void {
    //debugLog('This is SpriteGBLayerRender');
    if (this.gfxSpriteShow) {
      //Are sprites enabled?
      let lineAdjusted = scanlineToRender + GBEMU_0x10;
      let oamAddress = GBEMU_0xFE00;
      let yoffset = 0;
      let xcoord = 1;
      let xCoordStart = 0;
      let xCoordEnd = 0;
      let attrCode = 0;
      let palette = 0;
      let tile: TNextArray = new Int32Array();
      let data = 0;
      let spriteCount = 0;
      let length = 0;
      let currentPixel = 0;
      let linePixel = 0;
      //Clear our x-coord sort buffer:
      while (xcoord < GBEMU_168) {
        this.sortBuffer![xcoord++] = GBEMU_0xFF;
      }
      if (this.gfxSpriteNormalHeight) {
        //Draw the visible sprites:
        let length: number = this.findLowestSpriteDrawable(lineAdjusted, GBEMU_0x7);
        while (spriteCount < length) {
          oamAddress = this.oamAddressCache![spriteCount];
          yoffset = (lineAdjusted - this.memory[oamAddress]) << GBEMU_3;
          attrCode = this.memory[oamAddress | GBEMU_3];
          palette = (attrCode & GBEMU_0x10) >> GBEMU_2;
          tile = this.tileCache![((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2]].array;
          linePixel = this.memory[oamAddress | 1];
          xCoordStart = this.memory[oamAddress | 1];
          xCoordEnd = Math.min(GBEMU_168 - linePixel, GBEMU_8);
          xcoord = linePixel > GBEMU_7 ? 0 : GBEMU_8 - linePixel;
          currentPixel = this.pixelStart + (linePixel > GBEMU_8 ? linePixel - GBEMU_8 : 0);
          while (xcoord < xCoordEnd) {
            if (this.sortBuffer![linePixel] > xCoordStart) {
              if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                data = tile[yoffset | xcoord];
                if (data > 0) {
                  this.frameBuffer![currentPixel] = this.objPalette![palette | data];
                  this.sortBuffer![linePixel] = xCoordStart;
                }
              } else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                data = tile[yoffset | xcoord];
                if (data > 0 && attrCode < GBEMU_0x80) {
                  this.frameBuffer![currentPixel] = this.objPalette![palette | data];
                  this.sortBuffer![linePixel] = xCoordStart;
                }
              }
            }
            xcoord += 1;
            currentPixel += 1;
            linePixel += 1;
          }
          spriteCount += 1;
        }
      } else {
        //Draw the visible sprites:
        let length = this.findLowestSpriteDrawable(lineAdjusted, GBEMU_0xF);
        while (spriteCount < length) {
          oamAddress = this.oamAddressCache![spriteCount];
          yoffset = (lineAdjusted - this.memory[oamAddress]) << GBEMU_3;
          attrCode = this.memory[oamAddress | GBEMU_3];
          palette = (attrCode & GBEMU_0x10) >> GBEMU_2;
          if ((attrCode & GBEMU_0x40) === (GBEMU_0x40 & yoffset)) {
            tile = this.tileCache![((attrCode & GBEMU_0x60) << GBEMU_4) | (this.memory[oamAddress | GBEMU_0x2] & GBEMU_0xFE)].array;
          } else {
            tile = this.tileCache![((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2] | 1].array;
          }
          yoffset &= GBEMU_0x3F;
          xCoordStart = this.memory[oamAddress | 1];
          linePixel = xCoordStart;
          xCoordEnd = Math.min(GBEMU_168 - linePixel, GBEMU_8);
          xcoord = linePixel > GBEMU_7 ? 0 : GBEMU_8 - linePixel;
          currentPixel = this.pixelStart + (linePixel > GBEMU_8 ? linePixel - GBEMU_8 : 0);
          while (xcoord < xCoordEnd) {
            if (this.sortBuffer![linePixel] > xCoordStart) {
              if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                data = tile[yoffset | xcoord];
                if (data > 0) {
                  this.frameBuffer![currentPixel] = this.objPalette![palette | data];
                  this.sortBuffer![linePixel] = xCoordStart;
                }
              } else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                data = tile[yoffset | xcoord];
                if (data > 0 && attrCode < GBEMU_0x80) {
                  this.frameBuffer![currentPixel] = this.objPalette![palette | data];
                  this.sortBuffer![linePixel] = xCoordStart;
                }
              }
            }
            xcoord += 1;
            currentPixel += 1;
            linePixel += 1;
          }
          spriteCount += 1;
        }
      }
    }
  }
  findLowestSpriteDrawable(scanlineToRender: number, drawableRange: number): number {
    //debugLog('This is findLowestSpriteDrawable');
    let address = GBEMU_0xFE00;
    let spriteCount = 0;
    let diff = 0;
    while (address < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
      diff = scanlineToRender - this.memory[address];
      if ((diff & drawableRange) === diff) {
        this.oamAddressCache![spriteCount++] = address;
      }
      address += GBEMU_4;
    }
    return spriteCount;
  }
  spriteGBCLayerRender(scanlineToRender: number): void {
    if (this.gfxSpriteShow) {
      //Are sprites enabled?
      let oamAddress = GBEMU_0xFE00;
      let lineAdjusted = scanlineToRender + GBEMU_0x10;
      let yoffset = 0;
      let xcoord = 0;
      let endX = 0;
      let xCounter = 0;
      let attrCode = 0;
      let palette = 0;
      let tile: TNextArray | null = null;
      let data = 0;
      let currentPixel = 0;
      let spriteCount = 0;
      if (this.gfxSpriteNormalHeight) {
        while (oamAddress < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
          yoffset = lineAdjusted - this.memory[oamAddress];
          if ((yoffset & GBEMU_0x7) === yoffset) {
            xcoord = this.memory[oamAddress | 1] - GBEMU_8;
            endX = Math.min(GBEMU_160, xcoord + GBEMU_8);
            attrCode = this.memory[oamAddress | GBEMU_3];
            palette = (attrCode & GBEMU_7) << GBEMU_2;
            tile = this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_2]].array;
            xCounter = xcoord > 0 ? xcoord : 0;
            xcoord -= yoffset << GBEMU_3;
            currentPixel = this.pixelStart + xCounter;
            while (xCounter < endX) {
              if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                data = tile[xCounter - xcoord];
                if (data > 0) {
                  this.frameBuffer![currentPixel] = this.gbcOBJPalette![palette | data];
                }
              } else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                data = tile[xCounter - xcoord];
                if (data > 0 && attrCode < GBEMU_0x80) {
                  //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
                  this.frameBuffer![currentPixel] = this.gbcOBJPalette![palette | data];
                }
              }
              xCounter += 1;
              currentPixel += 1;
            }
            spriteCount += 1;
          }
          oamAddress += GBEMU_4;
        }
      } else {
        while (oamAddress < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
          yoffset = lineAdjusted - this.memory[oamAddress];
          if ((yoffset & GBEMU_0xF) === yoffset) {
            xcoord = this.memory[oamAddress | 1] - GBEMU_8;
            endX = Math.min(GBEMU_160, xcoord + GBEMU_8);
            attrCode = this.memory[oamAddress | GBEMU_3];
            palette = (attrCode & GBEMU_7) << GBEMU_2;
            if ((attrCode & GBEMU_0x40) === (GBEMU_0x40 & (yoffset << GBEMU_3))) {
              tile =
                this.tileCache![
                  ((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | (this.memory[oamAddress | GBEMU_0x2] & GBEMU_0xfe)
                ].array;
            } else {
              tile =
                this.tileCache![((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2] | 1].array;
            }
            xCounter = xcoord > 0 ? xcoord : 0;
            xcoord -= (yoffset & GBEMU_0x7) << GBEMU_3;
            currentPixel = this.pixelStart + xCounter;
            while (xCounter < endX) {
              if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                data = tile[xCounter - xcoord];
                if (data > 0) {
                  this.frameBuffer![currentPixel] = this.gbcOBJPalette![palette | data];
                }
              } else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                data = tile[xCounter - xcoord];
                if (data > 0 && attrCode < GBEMU_0x80) {
                  //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
                  this.frameBuffer![currentPixel] = this.gbcOBJPalette![palette | data];
                }
              }
              xCounter += 1;
              currentPixel += 1;
            }
            spriteCount += 1;
          }
          oamAddress += GBEMU_4;
        }
      }
    }
  }
  //Generate only a single tile line for the GB tile cache mode:
  generateGBTileLine(addressTemp: number): void {
    //debugLog('This is generateGBTileLine');
    let address = addressTemp;
    let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
    let tileBlock = this.tileCache![(address & GBEMU_0x1FF0) >> GBEMU_4];
    address = (address & GBEMU_0xE) << GBEMU_2;
    tileBlock.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
    tileBlock.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
    tileBlock.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
    tileBlock.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
    tileBlock.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
    tileBlock.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
    tileBlock.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
    tileBlock.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
  }
  //Generate only a single tile line for the GBC tile cache mode (Bank 1):
  generateGBCTileLineBank1(addressTemp: number) {
    let address = addressTemp;
    let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
    address &= GBEMU_0x1FFE;
    let tileBlock1 = this.tileCache![address >> GBEMU_4];
    let tileBlock2 = this.tileCache![GBEMU_0x200 | (address >> GBEMU_4)];
    let tileBlock3 = this.tileCache![GBEMU_0x400 | (address >> GBEMU_4)];
    let tileBlock4 = this.tileCache![GBEMU_0x600 | (address >> GBEMU_4)];
    address = (address & GBEMU_0xE) << GBEMU_2;
    let addressFlipped = GBEMU_0x38 - address;
    tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
    tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
    tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
    tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
    tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
    tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
    tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
    tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
    tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
    tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
    tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
    tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
    tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
    tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
    tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
    tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
    tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
    tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
    tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
    tileBlock3.array[addressFlipped] = tileBlock1.array[address];
  }
  //Generate all the flip combinations for a full GBC vram bank 1 tile:
  generateGBCTileBank1(vramAddressTemp: number): void {
    let vramAddress = vramAddressTemp;
    let address = vramAddress >> GBEMU_4;
    let tileBlock1 = this.tileCache![address];
    let tileBlock2 = this.tileCache![GBEMU_0x200 | address];
    let tileBlock3 = this.tileCache![GBEMU_0x400 | address];
    let tileBlock4 = this.tileCache![GBEMU_0x600 | address];
    let lineCopy = 0;
    vramAddress |= GBEMU_0x8000;
    address = 0;
    let addressFlipped = 56;
    do {
      lineCopy = (this.memory[GBEMU_0x1 | vramAddress] << GBEMU_8) | this.memory[vramAddress];
      tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
      tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
      tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
      tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
      tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
      tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
      tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
      tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
      tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
      tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
      tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
      tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
      tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
      tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
      tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
      tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
      tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
      tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
      tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
      tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
      tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
      tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
      tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
      tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
      tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
      tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
      tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
      tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
      tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
      tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
      tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
      tileBlock3.array[addressFlipped] = tileBlock1.array[address];
      address += GBEMU_8;
      addressFlipped -= GBEMU_8;
      vramAddress += GBEMU_2;
    } while (addressFlipped > -1);
  }
  //Generate only a single tile line for the GBC tile cache mode (Bank GBEMU_2):
  generateGBCTileLineBank2(addressTemp: number): void {
    //debugLog('This is generateGBCTileLineBank2');
    let address = addressTemp;
    let lineCopy = (this.vram![GBEMU_0x1 | address] << GBEMU_8) | this.vram![GBEMU_0x1FFE & address];
    let tileBlock1 = this.tileCache![GBEMU_0x800 | (address >> GBEMU_4)];
    let tileBlock2 = this.tileCache![GBEMU_0xA00 | (address >> GBEMU_4)];
    let tileBlock3 = this.tileCache![GBEMU_0xC00 | (address >> GBEMU_4)];
    let tileBlock4 = this.tileCache![GBEMU_0xE00 | (address >> GBEMU_4)];
    address = (address & GBEMU_0xE) << GBEMU_2;
    let addressFlipped = GBEMU_0x38 - address;
    tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
    tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
    tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
    tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
    tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
    tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
    tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
    tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
    tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
    tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
    tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
    tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
    tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
    tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
    tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
    tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
    tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
    tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
    tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
    tileBlock3.array[addressFlipped] = tileBlock1.array[address];
  }
  //Generate all the flip combinations for a full GBC vram bank GBEMU_2 tile:
  generateGBCTileBank2(vramAddressTemp: number): void {
    let vramAddress = vramAddressTemp;
    let address = vramAddress >> GBEMU_4;
    let tileBlock1 = this.tileCache![GBEMU_0x800 | address];
    let tileBlock2 = this.tileCache![GBEMU_0xA00 | address];
    let tileBlock3 = this.tileCache![GBEMU_0xC00 | address];
    let tileBlock4 = this.tileCache![GBEMU_0xE00 | address];
    let lineCopy = 0;
    address = 0;
    let addressFlipped = 56;
    do {
      lineCopy = (this.vram![GBEMU_0x1 | vramAddress] << GBEMU_8) | this.vram![vramAddress];
      tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
      tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
      tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
      tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
      tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
      tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
      tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
      tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
      tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
      tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
      tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
      tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
      tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
      tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
      tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
      tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
      tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
      tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
      tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
      tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
      tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
      tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
      tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
      tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
      tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
      tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
      tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
      tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
      tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
      tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
      tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
      tileBlock3.array[addressFlipped] = tileBlock1.array[address];
      address += GBEMU_8;
      addressFlipped -= GBEMU_8;
      vramAddress += GBEMU_2;
    } while (addressFlipped > -1);
  }
  //Generate only a single tile line for the GB tile cache mode (OAM accessible range):
  generateGBOAMTileLine(addressTemp: number): void {
    //debugLog('This is generateGBOAMTileLine');
    let address = addressTemp;
    let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
    address &= GBEMU_0x1FFE;
    let tileBlock1 = this.tileCache![address >> GBEMU_4];
    let tileBlock2 = this.tileCache![GBEMU_0x200 | (address >> GBEMU_4)];
    let tileBlock3 = this.tileCache![GBEMU_0x400 | (address >> GBEMU_4)];
    let tileBlock4 = this.tileCache![GBEMU_0x600 | (address >> GBEMU_4)];
    address = (address & GBEMU_0xE) << GBEMU_2;
    let addressFlipped = GBEMU_0x38 - address;
    tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
    tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
    tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
    tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
    tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
    tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
    tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
    tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
    tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
    tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
    tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
    tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
    tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
    tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
    tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
    tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
    tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
    tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
    tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
    tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
    tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
    tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
    tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
    tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
    tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
    tileBlock3.array[addressFlipped] = tileBlock1.array[address];
  }
  graphicsJIT(): void {
    if (this.lcdIsOn) {
      this.totalLinesPassed = 0; //Mark frame for ensuring a JIT pass for the next framebuffer output.
      this.graphicsJITScanlineGroup();
    }
  }
  graphicsJITVBlank(): void {
    //debugLog('This is graphicsJITVBlank');
    //JIT the graphics to v-blank framing:
    this.totalLinesPassed += this.queuedScanLines;
    this.graphicsJITScanlineGroup();
  }
  graphicsJITScanlineGroup(): void {
    //Normal rendering JIT, where we try to do groups of scanlines at once:
    while (this.queuedScanLines > 0) {
      this.renderScanLine(this.lastUnrenderedLine);
      if (this.lastUnrenderedLine < GBEMU_143) {
        this.lastUnrenderedLine += 1;
      } else {
        this.lastUnrenderedLine = 0;
      }
      this.queuedScanLines -= 1;
    }
  }
  incrementScanLineQueue(): void {
    if (this.queuedScanLines < GBEMU_144) {
      this.queuedScanLines += 1;
    } else {
      this.currentX = 0;
      this.midScanlineOffset = -1;
      if (this.lastUnrenderedLine < GBEMU_143) {
        this.lastUnrenderedLine += 1;
      } else {
        this.lastUnrenderedLine = 0;
      }
    }
  }
  midScanLineJIT(): void {
    this.graphicsJIT();
    this.renderMidScanLine();
  }
  //Check for the highest priority IRQ to fire:
  launchIRQ(): void {
    //debugLog('This is launchIRQ');
    let bitShift = 0;
    let testbit = 1;
    do {
      //Check to see if an interrupt is enabled AND requested.
      if ((testbit & this.irqLineMatched) === testbit) {
        this.ime = false; //Reset the interrupt enabling.
        this.interruptsRequested -= testbit; //Reset the interrupt request.
        this.irqLineMatched = GBEMU_0; //Reset the IRQ assertion.
        //Interrupts have a certain clock cycle length:
        this.cpuTicks = GBEMU_20;
        //Set the stack pointer to the current program counter value:
        this.stackPointer = (this.stackPointer - 1) & GBEMU_0xFFFF;
        this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter >> GBEMU_8);
        this.stackPointer = (this.stackPointer - 1) & GBEMU_0xFFFF;
        this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter & GBEMU_0xFF);
        //Set the program counter to the interrupt's address:
        this.programCounter = GBEMU_0x40 | (bitShift << GBEMU_3);
        //Clock the core for mid-instruction updates:
        this.updateCore();
        return; //We only want the highest priority interrupt.
      }
      bitShift += 1;
      testbit = 1 << bitShift;
    } while (bitShift < GBEMU_5);
  }
  /*
  Check for IRQs to be fired while not in HALT:
*/
  checkIRQMatching(): void {
    if (this.ime) {
      this.irqLineMatched = this.interruptsEnabled & this.interruptsRequested & GBEMU_0x1f;
    }
  }

  calculateHALTPeriod(): void {
    //debugLog('This is calculateHALTPeriod');
    //Initialize our variables and start our prediction:
    let currentClocks = 0;
    if (!this.halt) {
      this.halt = true;
      currentClocks = -1;
      let tempVar = 0;
      if (this.lcdIsOn) {
        //If the LCD is enabled, then predict the LCD IRQs enabled:
        if ((this.interruptsEnabled & GBEMU_0x1) === GBEMU_0x1) {
          currentClocks = (GBEMU_456 * ((this.modeSTAT === 1 ? GBEMU_298 : GBEMU_144) - this.actualScanLine) - this.lcdTicks) << this.doubleSpeedShifter;
        }
        if ((this.interruptsEnabled & GBEMU_0x2) === GBEMU_0x2) {
          if (this.mode0TriggerSTAT) {
            tempVar = (this.clocksUntilMode0() - this.lcdTicks) << this.doubleSpeedShifter;
            if (tempVar <= currentClocks || currentClocks === -1) {
              currentClocks = tempVar;
            }
          }
          if (this.mode1TriggerSTAT && (this.interruptsEnabled & GBEMU_0x1) === 0) {
            tempVar = (GBEMU_456 * ((this.modeSTAT === 1 ? GBEMU_298 : GBEMU_144) - this.actualScanLine) - this.lcdTicks) << this.doubleSpeedShifter;
            if (tempVar <= currentClocks || currentClocks === -1) {
              currentClocks = tempVar;
            }
          }
          if (this.mode2TriggerSTAT) {
            tempVar =
              ((this.actualScanLine >= GBEMU_143 ? GBEMU_456 * (GBEMU_154 - this.actualScanLine) : GBEMU_456) - this.lcdTicks) << this.doubleSpeedShifter;
            if (tempVar <= currentClocks || currentClocks === -1) {
              currentClocks = tempVar;
            }
          }
          if (this.lycMatchTriggerSTAT && this.memory[GBEMU_0xFF45] <= GBEMU_153) {
            tempVar = (this.clocksUntilLYCMatch() - this.lcdTicks) << this.doubleSpeedShifter;
            if (tempVar <= currentClocks || currentClocks === -1) {
              currentClocks = tempVar;
            }
          }
        }
      }
      if (this.timaEnabled && (this.interruptsEnabled & GBEMU_0x4) === GBEMU_0x4) {
        //CPU timer IRQ prediction:
        tempVar = (GBEMU_0x100 - this.memory[GBEMU_0xFF05]) * this.tacClocker - this.timerTicks;
        if (tempVar <= currentClocks || currentClocks === -1) {
          currentClocks = tempVar;
        }
      }
      if (this.serialTimer > 0 && (this.interruptsEnabled & GBEMU_0x8) === GBEMU_0x8) {
        //Serial IRQ prediction:
        if (this.serialTimer <= currentClocks || currentClocks === -1) {
          currentClocks = this.serialTimer;
        }
      }
    } else {
      currentClocks = this.remainingClocks;
    }
    let maxClocks = (this.cpuCyclesTotal - this.emulatorTicks) << this.doubleSpeedShifter;
    if (currentClocks >= GBEMU_0) {
      if (currentClocks <= maxClocks) {
        this.cpuTicks = Math.max(currentClocks, this.cpuTicks);
        this.updateCoreFull();
        this.halt = false;
        this.cpuTicks = GBEMU_0;
      } else {
        this.cpuTicks = Math.max(maxClocks, this.cpuTicks);
        this.remainingClocks = currentClocks - this.cpuTicks;
      }
    } else {
      this.cpuTicks += maxClocks;
    }
  }
  //Memory Reading:
  memoryRead(address: number): number {
    //Act as a wrapper for reading the returns from the compiled jumps to memory.
    return this.memoryReader[address](this, address); //This seems to be faster than the usual if/else.
  }
  memoryHighRead(address: number): number {
    //Act as a wrapper for reading the returns from the compiled jumps to memory.
    return this.memoryHighReader[address](this, address); //This seems to be faster than the usual if/else.
  }
  memoryReadJumpCompile(): void {
    //debugLog('This is memoryReadJumpCompile');
    //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
    for (let index = GBEMU_0x0000; index <= GBEMU_0xFFFF; index++) {
      if (index < GBEMU_0x4000) {
        this.memoryReader[index] = this.memoryReadNormal;
      } else if (index < GBEMU_0x8000) {
        this.memoryReader[index] = this.memoryReadrom;
      } else if (index < GBEMU_0x9800) {
        this.memoryReader[index] = this.cGBC ? this.vRAMDATAReadCGBCPU : this.vRAMDATAReadDMGCPU;
      } else if (index < GBEMU_0xA000) {
        this.memoryReader[index] = this.cGBC ? this.vRAMCHRReadCGBCPU : this.vRAMCHRReadDMGCPU;
      } else if (index >= GBEMU_0xA000 && index < GBEMU_0xC000) {
        if ((this.numRamBanks === 1 / GBEMU_16 && index < GBEMU_0xA200) || this.numRamBanks >= 1) {
          if (this.cMBC7) {
            this.memoryReader[index] = this.memoryReadMBC7;
          } else if (!this.cMBC3) {
            this.memoryReader[index] = this.memoryReadMBC;
          } else {
            this.memoryReader[index] = this.memoryReadMBC3; //MBC3 RTC + RAM
          }
        } else {
          this.memoryReader[index] = this.memoryReadBAD;
        }
      } else if (index >= GBEMU_0xC000 && index < GBEMU_0xE000) {
        if (!this.cGBC || index < GBEMU_0xD000) {
          this.memoryReader[index] = this.memoryReadNormal;
        } else {
          this.memoryReader[index] = this.memoryReadgbcMemory;
        }
      } else if (index >= GBEMU_0xE000 && index < GBEMU_0xFE00) {
        if (!this.cGBC || index < GBEMU_0xF000) {
          this.memoryReader[index] = this.memoryReadECHONormal;
        } else {
          this.memoryReader[index] = this.memoryReadECHOgbcMemory;
        }
      } else if (index < GBEMU_0xFEA0) {
        this.memoryReader[index] = this.memoryReadOAM;
      } else if (this.cGBC && index >= GBEMU_0xFEA0 && index < GBEMU_0xFF00) {
        this.memoryReader[index] = this.memoryReadNormal;
      } else if (index >= GBEMU_0xFF00) {
        switch (index) {
          case GBEMU_0xFF00:
            //JOYPAD:
            this.memoryReader[GBEMU_0xFF00] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xC0 | parentObj.memory[GBEMU_0xFF00]; //Top nibble returns as set.
            };
            this.memoryHighReader[0] = this.memoryReader[GBEMU_0xFF00];
            break;
          case GBEMU_0xFF01:
            //SB
            this.memoryReader[GBEMU_0xFF01] = (parentObj: GameBoyCore, address: number) => {
              return parentObj.memory[GBEMU_0xFF02] < GBEMU_0x80 ? parentObj.memory[GBEMU_0xFF01] : GBEMU_0xFF;
            };
            this.memoryHighReader[GBEMU_0x01] = this.memoryReader[GBEMU_0xFF01];
            break;
          case GBEMU_0xFF02:
            //SC
            if (this.cGBC) {
              this.memoryReader[GBEMU_0xFF02] = (parentObj: GameBoyCore, address: number) => {
                return (parentObj.serialTimer <= 0 ? GBEMU_0x7C : GBEMU_0xFC) | parentObj.memory[GBEMU_0xFF02];
              };
              this.memoryHighReader[GBEMU_0x02] = this.memoryReader[GBEMU_0xFF02];
            } else {
              this.memoryReader[GBEMU_0xFF02] = (parentObj: GameBoyCore, address: number) => {
                return (parentObj.serialTimer <= 0 ? GBEMU_0x7E : GBEMU_0xFE) | parentObj.memory[GBEMU_0xFF02];
              };
              this.memoryHighReader[GBEMU_0x02] = this.memoryReader[GBEMU_0xFF02];
            }
            break;
          case GBEMU_0xFF04:
            //DIV
            this.memoryReader[GBEMU_0xFF04] = (parentObj: GameBoyCore, address: number) => {
              parentObj.memory[GBEMU_0xFF04] = (parentObj.memory[GBEMU_0xFF04] + (parentObj.divTicks >> GBEMU_8)) & GBEMU_0xFF;
              parentObj.divTicks &= GBEMU_0xFF;
              return parentObj.memory[GBEMU_0xFF04];
            };
            this.memoryHighReader[GBEMU_0x04] = this.memoryReader[GBEMU_0xFF04];
            break;
          case GBEMU_0xFF07:
            this.memoryReader[GBEMU_0xFF07] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xF8 | parentObj.memory[GBEMU_0xFF07];
            };
            this.memoryHighReader[GBEMU_0x07] = this.memoryReader[GBEMU_0xFF07];
            break;
          case GBEMU_0xFF0F:
            //IF
            this.memoryReader[GBEMU_0xFF0F] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xE0 | parentObj.interruptsRequested;
            };
            this.memoryHighReader[GBEMU_0x0F] = this.memoryReader[GBEMU_0xFF0F];
            break;
          case GBEMU_0xFF10:
            this.memoryReader[GBEMU_0xFF10] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0x80 | parentObj.memory[GBEMU_0xFF10];
            };
            this.memoryHighReader[GBEMU_0x10] = this.memoryReader[GBEMU_0xFF10];
            break;
          case GBEMU_0xFF11:
            this.memoryReader[GBEMU_0xFF11] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0x3F | parentObj.memory[GBEMU_0xFF11];
            };
            this.memoryHighReader[GBEMU_0x11] = this.memoryReader[GBEMU_0xFF11];
            break;
          case GBEMU_0xFF13:
            this.memoryHighReader[GBEMU_0x13] = this.memoryReadBAD;
            this.memoryReader[GBEMU_0xFF13] = this.memoryReadBAD;
            break;
          case GBEMU_0xFF14:
            this.memoryReader[GBEMU_0xFF14] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF14];
            };
            this.memoryHighReader[GBEMU_0x14] = this.memoryReader[GBEMU_0xFF14];
            break;
          case GBEMU_0xFF16:
            this.memoryReader[GBEMU_0xFF16] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0x3F | parentObj.memory[GBEMU_0xFF16];
            };
            this.memoryHighReader[GBEMU_0x16] = this.memoryReader[GBEMU_0xFF16];
            break;
          case GBEMU_0xFF18:
            this.memoryHighReader[GBEMU_0x18] = this.memoryReadBAD;
            this.memoryReader[GBEMU_0xFF18] = this.memoryReadBAD;
            break;
          case GBEMU_0xFF19:
            this.memoryReader[GBEMU_0xFF19] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF19];
            };
            this.memoryHighReader[GBEMU_0x19] = this.memoryReader[GBEMU_0xFF19];
            break;
          case GBEMU_0xFF1A:
            this.memoryReader[GBEMU_0xFF1A] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0x7F | parentObj.memory[GBEMU_0xFF1A];
            };
            this.memoryHighReader[GBEMU_0x1A] = this.memoryReader[GBEMU_0xFF1A];
            break;
          case GBEMU_0xFF1B:
            this.memoryHighReader[GBEMU_0x1B] = this.memoryReadBAD;
            this.memoryReader[GBEMU_0xFF1B] = this.memoryReadBAD;
            break;
          case GBEMU_0xFF1C:
            this.memoryReader[GBEMU_0xFF1C] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0x9F | parentObj.memory[GBEMU_0xFF1C];
            };
            this.memoryHighReader[GBEMU_0x1C] = this.memoryReader[GBEMU_0xFF1C];
            break;
          case GBEMU_0xFF1D:
            this.memoryReader[GBEMU_0xFF1D] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xFF;
            };
            this.memoryHighReader[GBEMU_0x1D] = this.memoryReader[GBEMU_0xFF1D];
            break;
          case GBEMU_0xFF1E:
            this.memoryReader[GBEMU_0xFF1E] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF1E];
            };
            this.memoryHighReader[GBEMU_0x1E] = this.memoryReader[GBEMU_0xFF1E];
            break;
          case GBEMU_0xFF1F:
          case GBEMU_0xFF20:
            this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReadBAD;
            this.memoryReader[index] = this.memoryReadBAD;
            break;
          case GBEMU_0xFF23:
            this.memoryReader[GBEMU_0xFF23] = (parentObj: GameBoyCore, address: number) => {
              return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF23];
            };
            this.memoryHighReader[GBEMU_0x23] = this.memoryReader[GBEMU_0xFF23];
            break;
          case GBEMU_0xFF26:
            this.memoryReader[GBEMU_0xFF26] = (parentObj: GameBoyCore, address: number) => {
              parentObj.audioJIT();
              return GBEMU_0x70 | parentObj.memory[GBEMU_0xFF26];
            };
            this.memoryHighReader[GBEMU_0x26] = this.memoryReader[GBEMU_0xFF26];
            break;
          case GBEMU_0xFF27:
          case GBEMU_0xFF28:
          case GBEMU_0xFF29:
          case GBEMU_0xFF2A:
          case GBEMU_0xFF2B:
          case GBEMU_0xFF2C:
          case GBEMU_0xFF2D:
          case GBEMU_0xFF2E:
          case GBEMU_0xFF2F:
            this.memoryReader[index] = this.memoryReadBAD;
            this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReader[index];
            break;
          case GBEMU_0xFF30:
          case GBEMU_0xFF31:
          case GBEMU_0xFF32:
          case GBEMU_0xFF33:
          case GBEMU_0xFF34:
          case GBEMU_0xFF35:
          case GBEMU_0xFF36:
          case GBEMU_0xFF37:
          case GBEMU_0xFF38:
          case GBEMU_0xFF39:
          case GBEMU_0xFF3A:
          case GBEMU_0xFF3B:
          case GBEMU_0xFF3C:
          case GBEMU_0xFF3D:
          case GBEMU_0xFF3E:
          case GBEMU_0xFF3F:
            this.memoryReader[index] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.channel3canPlay ? parentObj.memory[GBEMU_0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] : parentObj.memory[address];
            };
            this.memoryHighReader[index & GBEMU_0xFF] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.channel3canPlay ?
                parentObj.memory[GBEMU_0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] :
                parentObj.memory[GBEMU_0xFF00 | address];
            };
            break;
          case GBEMU_0xFF41:
            this.memoryReader[GBEMU_0xFF41] = (parentObj: GameBoyCore, address: number): number => {
              return GBEMU_0x80 | parentObj.memory[GBEMU_0xFF41] | parentObj.modeSTAT;
            };
            this.memoryHighReader[GBEMU_0x41] = this.memoryReader[GBEMU_0xFF41];
            break;
          case GBEMU_0xFF42:
            this.memoryReader[GBEMU_0xFF42] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.backgroundY;
            };
            this.memoryHighReader[GBEMU_0x42] = this.memoryReader[GBEMU_0xFF42];
            break;
          case GBEMU_0xFF43:
            this.memoryReader[GBEMU_0xFF43] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.backgroundX;
            };
            this.memoryHighReader[GBEMU_0x43] = this.memoryReader[GBEMU_0xFF43];
            break;
          case GBEMU_0xFF44:
            this.memoryReader[GBEMU_0xFF44] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.lcdIsOn ? parentObj.memory[GBEMU_0xFF44] : 0;
            };
            this.memoryHighReader[GBEMU_0x44] = this.memoryReader[GBEMU_0xFF44];
            break;
          case GBEMU_0xFF4A:
            //WY
            this.memoryReader[GBEMU_0xFF4A] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.windowY;
            };
            this.memoryHighReader[GBEMU_0x4A] = this.memoryReader[GBEMU_0xFF4A];
            break;
          case GBEMU_0xFF4F:
            this.memoryReader[GBEMU_0xFF4F] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.currvramBank;
            };
            this.memoryHighReader[GBEMU_0x4F] = this.memoryReader[GBEMU_0xFF4F];
            break;
          case GBEMU_0xFF55:
            if (this.cGBC) {
              this.memoryReader[GBEMU_0xFF55] = (parentObj: GameBoyCore, address: number): number => {
                if (!parentObj.lcdIsOn && parentObj.hdmaRunning) {
                  //Undocumented behavior alert: HDMA becomes GDMA when LCD is oFF (Worms Armageddon Fix).
                  //DMA
                  parentObj.dMAWrite((parentObj.memory[GBEMU_0xFF55] & GBEMU_0x7f) + 1);
                  parentObj.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed.
                  parentObj.hdmaRunning = false;
                }
                return parentObj.memory[GBEMU_0xFF55];
              };
              this.memoryHighReader[GBEMU_0x55] = this.memoryReader[GBEMU_0xFF55];
            } else {
              this.memoryReader[GBEMU_0xFF55] = this.memoryReadNormal;
              this.memoryHighReader[GBEMU_0x55] = this.memoryHighReadNormal;
            }
            break;
          case GBEMU_0xFF56:
            if (this.cGBC) {
              this.memoryReader[GBEMU_0xFF56] = (parentObj: GameBoyCore, address: number): number => {
                //Return IR 'not connected' status:
                return (
                  GBEMU_0x3C |
                  (parentObj.memory[GBEMU_0xFF56] >= GBEMU_0xC0 ?
                    GBEMU_0x2 | (parentObj.memory[GBEMU_0xFF56] & GBEMU_0xC1) :
                    parentObj.memory[GBEMU_0xFF56] & GBEMU_0xC3)
                );
              };
              this.memoryHighReader[GBEMU_0x56] = this.memoryReader[GBEMU_0xFF56];
            } else {
              this.memoryReader[GBEMU_0xFF56] = this.memoryReadNormal;
              this.memoryHighReader[GBEMU_0x56] = this.memoryHighReadNormal;
            }
            break;
          case GBEMU_0xFF6C:
            if (this.cGBC) {
              this.memoryReader[GBEMU_0xFF6C] = (parentObj: GameBoyCore, address: number): number => {
                return GBEMU_0xFE | parentObj.memory[GBEMU_0xFF6C];
              };
              this.memoryHighReader[GBEMU_0x6c] = this.memoryReader[GBEMU_0xFF6C];
            } else {
              this.memoryReader[GBEMU_0xFF6C] = this.memoryReadBAD;
              this.memoryHighReader[GBEMU_0x6C] = this.memoryReadBAD;
            }
            break;
          case GBEMU_0xFF70:
            if (this.cGBC) {
              //SVBK
              this.memoryReader[GBEMU_0xFF70] = (parentObj: GameBoyCore, address: number): number => {
                return GBEMU_0x40 | parentObj.memory[GBEMU_0xFF70];
              };
              this.memoryHighReader[GBEMU_0x70] = this.memoryReader[GBEMU_0xFF70];
            } else {
              this.memoryReader[GBEMU_0xFF70] = this.memoryReadBAD;
              this.memoryHighReader[GBEMU_0x70] = this.memoryReadBAD;
            }
            break;
          case GBEMU_0xFF75:
            this.memoryReader[GBEMU_0xFF75] = (parentObj: GameBoyCore, address: number): number => {
              return GBEMU_0x8F | parentObj.memory[GBEMU_0xFF75];
            };
            this.memoryHighReader[GBEMU_0x75] = this.memoryReader[GBEMU_0xFF75];
            break;
          case GBEMU_0xFF76:
          case GBEMU_0xFF77:
            this.memoryReader[index] = (parentObj: GameBoyCore, address: number): number => {
              return 0;
            };
            this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReader[index];
            break;
          case GBEMU_0xFFFF:
            //IE
            this.memoryReader[GBEMU_0xFFFF] = (parentObj: GameBoyCore, address: number): number => {
              return parentObj.interruptsEnabled;
            };
            this.memoryHighReader[GBEMU_0xFF] = this.memoryReader[GBEMU_0xFFFF];
            break;
          default:
            this.memoryReader[index] = this.memoryReadNormal;
            this.memoryHighReader[index & GBEMU_0xFF] = this.memoryHighReadNormal;
        }
      } else {
        this.memoryReader[index] = this.memoryReadBAD;
      }
    }
  }
  memoryReadNormal(parentObj: GameBoyCore, address: number): number {
    return parentObj.memory[address];
  }
  memoryHighReadNormal(parentObj: GameBoyCore, address: number): number {
    return parentObj.memory[GBEMU_0xFF00 | address];
  }
  memoryReadrom(parentObj: GameBoyCore, address: number): number {
    return parentObj.rom[parentObj.currentromBank + address];
  }
  memoryReadMBC(parentObj: GameBoyCore, address: number): number {
    //Switchable RAM
    if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
      return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
    }
    //cout('Reading from disabled RAM.', 1);
    return GBEMU_0xFF;
  }
  memoryReadMBC7(parentObj: GameBoyCore, address: number): number {
    //debugLog('This is memoryReadMBC7');
    //Switchable RAM
    if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
      switch (address) {
        case GBEMU_0xA000:
        case GBEMU_0xA060:
        case GBEMU_0xA070:
          return 0;
        case GBEMU_0xA080:
          //TODO: Gyro Control Register
          return 0;
        case GBEMU_0xA050:
          //Y High Byte
          return parentObj.highY;
        case GBEMU_0xA040:
          //Y Low Byte
          return parentObj.lowY;
        case GBEMU_0xA030:
          //X High Byte
          return parentObj.highX;
        case GBEMU_0xA020:
          //X Low Byte:
          return parentObj.lowX;
        default:
          return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
      }
    }
    //cout('Reading from disabled RAM.', 1);
    return GBEMU_0xFF;
  }
  memoryReadMBC3(parentObj: GameBoyCore, address: number): number {
    //debugLog('This is memoryReadMBC3');
    //Switchable RAM
    if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
      switch (parentObj.currMBCRAMBank) {
        case GBEMU_0x00:
        case GBEMU_0x01:
        case GBEMU_0x02:
        case GBEMU_0x03:
          return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
        case GBEMU_0x08:
          return parentObj.latchedSeconds;
        case GBEMU_0x09:
          return parentObj.latchedMinutes;
        case GBEMU_0x0A:
          return parentObj.latchedHours;
        case GBEMU_0x0B:
          return parentObj.latchedLDays;
        case GBEMU_0x0C:
          return (parentObj.rtcDayOverFlow ? GBEMU_0x80 : 0) + (parentObj.rtcHalt ? GBEMU_0x40 : 0) + parentObj.latchedHDays;
        default:
          return 0;
      }
    }
    //cout('Reading from invalid or disabled RAM.', 1);
    return GBEMU_0xFF;
  }
  memoryReadgbcMemory(parentObj: GameBoyCore, address: number): number {
    return parentObj.gbcMemory![address + parentObj.gbcRamBankPosition];
  }
  memoryReadOAM(parentObj: GameBoyCore, address: number): number {
    return parentObj.modeSTAT > 1 ? GBEMU_0xFF : parentObj.memory[address];
  }
  memoryReadECHOgbcMemory(parentObj: GameBoyCore, address: number): number {
    return parentObj.gbcMemory![address + parentObj.gbcRamBankPositionECHO];
  }
  memoryReadECHONormal(parentObj: GameBoyCore, address: number): number {
    return parentObj.memory[address - GBEMU_0x2000];
  }
  memoryReadBAD(parentObj: GameBoyCore, address: number): number {
    return GBEMU_0xFF;
  }
  vRAMDATAReadCGBCPU(parentObj: GameBoyCore, address: number): number {
    //CPU Side Reading The vram (Optimized for GameBoy Color)
    return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.currvramBank === 0 ? parentObj.memory[address] : parentObj.vram![address & GBEMU_0x1fff];
  }
  vRAMDATAReadDMGCPU(parentObj: GameBoyCore, address: number): number {
    //CPU Side Reading The vram (Optimized for classic GameBoy)
    return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.memory[address];
  }
  vRAMCHRReadCGBCPU(parentObj: GameBoyCore, address: number): number {
    //CPU Side Reading the Character Data Map:
    return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.bgCHRCurrentBank!.array[address & GBEMU_0x7FF];
  }
  vRAMCHRReadDMGCPU(parentObj: GameBoyCore, address: number): number {
    //CPU Side Reading the Character Data Map:
    return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.bgCHRBank1!.array[address & GBEMU_0x7FF];
  }
  setCurrentMBC1romBank(): void {
    //debugLog('This is setCurrentMBC1romBank');
    //Read the cartridge rom data from RAM memory:
    switch (this.romBank1offs) {
      case GBEMU_0x00:
      case GBEMU_0x20:
      case GBEMU_0x40:
      case GBEMU_0x60:
        //Bank calls for 0x00, 0x20, 0x40, and 0x60 are really for 0x01, 0x21, 0x41, and 0x61.
        this.currentromBank = this.romBank1offs % this.romBankEdge << GBEMU_14;
        break;
      default:
        this.currentromBank = ((this.romBank1offs % this.romBankEdge) - 1) << GBEMU_14;
    }
  }
  setCurrentMBC2AND3romBank(): void {
    //Read the cartridge rom data from RAM memory:
    //Only map bank 0 to bank 1 here (MBC2 is like MBC1, but can only do GBEMU_16 banks, so only the bank 0 quirk appears for MBC2):
    this.currentromBank = Math.max((this.romBank1offs % this.romBankEdge) - 1, 0) << GBEMU_14;
  }
  setCurrentMBC5romBank(): void {
    //Read the cartridge rom data from RAM memory:
    this.currentromBank = ((this.romBank1offs % this.romBankEdge) - 1) << GBEMU_14;
  }
  //Memory Writing:
  memoryWrite(address: number, data: number): void {
    //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
    this.memoryWriter[address](this, address, data);
  }
  //0xFFXX fast path:
  memoryHighWrite(address: number, data: number): void {
    //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
    this.memoryHighWriter[address](this, address, data);
  }
  memoryWriteJumpCompile(): void {
    //debugLog('This is memoryWriteJumpCompile');
    //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
    for (let index = GBEMU_0x0000; index <= GBEMU_0xFFFF; index++) {
      if (index < GBEMU_0x8000) {
        if (this.cMBC1) {
          if (index < GBEMU_0x2000) {
            this.memoryWriter[index] = this.mBCWriteEnable;
          } else if (index < GBEMU_0x4000) {
            this.memoryWriter[index] = this.mBC1WriteromBank;
          } else if (index < GBEMU_0x6000) {
            this.memoryWriter[index] = this.mBC1WriteRAMBank;
          } else {
            this.memoryWriter[index] = this.mBC1WriteType;
          }
        } else if (this.cMBC2) {
          if (index < GBEMU_0x1000) {
            this.memoryWriter[index] = this.mBCWriteEnable;
          } else if (index >= GBEMU_0x2100 && index < GBEMU_0x2200) {
            this.memoryWriter[index] = this.mBC2WriteromBank;
          } else {
            this.memoryWriter[index] = this.cartIgnoreWrite;
          }
        } else if (this.cMBC3) {
          if (index < GBEMU_0x2000) {
            this.memoryWriter[index] = this.mBCWriteEnable;
          } else if (index < GBEMU_0x4000) {
            this.memoryWriter[index] = this.mBC3WriteromBank;
          } else if (index < GBEMU_0x6000) {
            this.memoryWriter[index] = this.mBC3WriteRAMBank;
          } else {
            this.memoryWriter[index] = this.mBC3WriteRTCLatch;
          }
        } else if (this.cMBC5 || this.cRUMBLE || this.cMBC7) {
          if (index < GBEMU_0x2000) {
            this.memoryWriter[index] = this.mBCWriteEnable;
          } else if (index < GBEMU_0x3000) {
            this.memoryWriter[index] = this.mBC5WriteromBankLow;
          } else if (index < GBEMU_0x4000) {
            this.memoryWriter[index] = this.mBC5WriteromBankHigh;
          } else if (index < GBEMU_0x6000) {
            this.memoryWriter[index] = this.cRUMBLE ? this.rUMBLEWriteRAMBank : this.mBC5WriteRAMBank;
          } else {
            this.memoryWriter[index] = this.cartIgnoreWrite;
          }
        } else if (this.cHuC3) {
          if (index < GBEMU_0x2000) {
            this.memoryWriter[index] = this.mBCWriteEnable;
          } else if (index < GBEMU_0x4000) {
            this.memoryWriter[index] = this.mBC3WriteromBank;
          } else if (index < GBEMU_0x6000) {
            this.memoryWriter[index] = this.huC3WriteRAMBank;
          } else {
            this.memoryWriter[index] = this.cartIgnoreWrite;
          }
        } else {
          this.memoryWriter[index] = this.cartIgnoreWrite;
        }
      } else if (index < GBEMU_0x9000) {
        this.memoryWriter[index] = this.cGBC ? this.vRAMGBCDATAWrite : this.vRAMGBDATAWrite;
      } else if (index < GBEMU_0x9800) {
        this.memoryWriter[index] = this.cGBC ? this.vRAMGBCDATAWrite : this.vRAMGBDATAUpperWrite;
      } else if (index < GBEMU_0xA000) {
        this.memoryWriter[index] = this.cGBC ? this.vRAMGBCCHRMAPWrite : this.vRAMGBCHRMAPWrite;
      } else if (index < GBEMU_0xC000) {
        if ((this.numRamBanks === 1 / GBEMU_16 && index < GBEMU_0xA200) || this.numRamBanks >= 1) {
          if (!this.cMBC3) {
            this.memoryWriter[index] = this.memoryWriteMBCRAM;
          } else {
            this.memoryWriter[index] = this.memoryWriteMBC3RAM; //MBC3 RTC + RAM
          }
        } else {
          this.memoryWriter[index] = this.cartIgnoreWrite;
        }
      } else if (index < GBEMU_0xE000) {
        if (this.cGBC && index >= GBEMU_0xD000) {
          this.memoryWriter[index] = this.memoryWriteGBCRAM;
        } else {
          this.memoryWriter[index] = this.memoryWriteNormal;
        }
      } else if (index < GBEMU_0xFE00) {
        if (this.cGBC && index >= GBEMU_0xF000) {
          this.memoryWriter[index] = this.memoryWriteECHOGBCRAM;
        } else {
          this.memoryWriter[index] = this.memoryWriteECHONormal;
        }
      } else if (index <= GBEMU_0xFEA0) {
        this.memoryWriter[index] = this.memoryWriteOAMRAM;
      } else if (index < GBEMU_0xFF00) {
        if (this.cGBC) {
          //Only GBC has access to this RAM.
          this.memoryWriter[index] = this.memoryWriteNormal;
        } else {
          this.memoryWriter[index] = this.cartIgnoreWrite;
        }
      } else {
        this.memoryWriter[index] = this.memoryWriteNormal;
        this.memoryHighWriter[index & GBEMU_0xFF] = this.memoryHighWriteNormal;
      }
    }
    this.registerWriteJumpCompile(); //Compile the I/O write functions separately...
  }
  mBCWriteEnable(parentObj: GameBoyCore | null, address: number | null, data: number | null): void {
    //debugLog('This is MBCWriteEnable');
    //MBC RAM Bank Enable/Disable:
    parentObj!.mbcRamBanksEnabled = (data! & GBEMU_0x0F) === GBEMU_0x0A; //If lower nibble is GBEMU_0x0A, then enable, otherwise disable.
  }
  mBC1WriteromBank(parentObj: GameBoyCore, address: number, data: number): void {
    //debugLog('This is MBC1WriteromBank');
    //MBC1 rom bank switching:
    parentObj.romBank1offs = (parentObj.romBank1offs & GBEMU_0x60) | (data & GBEMU_0x1F);
    parentObj.setCurrentMBC1romBank();
  }
  mBC1WriteRAMBank(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC1 RAM bank switching
    if (parentObj.mbc1Mode) {
      //GBEMU_4/GBEMU_32 Mode
      parentObj.currMBCRAMBank = data & GBEMU_0x03;
      parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
    } else {
      //GBEMU_16/GBEMU_8 Mode
      parentObj.romBank1offs = ((data & GBEMU_0x03) << GBEMU_5) | (parentObj.romBank1offs & GBEMU_0x1F);
      parentObj.setCurrentMBC1romBank();
    }
  }
  mBC1WriteType(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC1 mode setting:
    parentObj.mbc1Mode = (data & GBEMU_0x1) === GBEMU_0x1;
    if (parentObj.mbc1Mode) {
      parentObj.romBank1offs &= GBEMU_0x1F;
      parentObj.setCurrentMBC1romBank();
    } else {
      parentObj.currMBCRAMBank = 0;
      parentObj.currMBCRAMBankPosition = -GBEMU_0xA000;
    }
  }
  mBC2WriteromBank(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC2 rom bank switching:
    parentObj.romBank1offs = data & GBEMU_0x0F;
    parentObj.setCurrentMBC2AND3romBank();
  }
  mBC3WriteromBank(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC3 rom bank switching:
    parentObj.romBank1offs = data & GBEMU_0x7F;
    parentObj.setCurrentMBC2AND3romBank();
  }
  mBC3WriteRAMBank(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj.currMBCRAMBank = data;
    if (data < GBEMU_4) {
      //MBC3 RAM bank switching
      parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
    }
  }
  mBC3WriteRTCLatch(parentObj: GameBoyCore, address: number, data: number): void {
    if (data === 0) {
      parentObj.rtcIsLatched = false;
    } else if (!parentObj.rtcIsLatched) {
      //Copy over the current RTC time for reading.
      parentObj.rtcIsLatched = true;
      parentObj.latchedSeconds = parentObj.rtcSeconds | GBEMU_0;
      parentObj.latchedMinutes = parentObj.rtcMinutes;
      parentObj.latchedHours = parentObj.rtcHours;
      parentObj.latchedLDays = parentObj.rtcDays & GBEMU_0xFF;
      parentObj.latchedHDays = parentObj.rtcDays >> GBEMU_8;
    }
  }
  mBC5WriteromBankLow(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC5 rom bank switching:
    parentObj.romBank1offs = (parentObj.romBank1offs & GBEMU_0x100) | data;
    parentObj.setCurrentMBC5romBank();
  }
  mBC5WriteromBankHigh(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC5 rom bank switching (by least significant bit):
    parentObj.romBank1offs = ((data & GBEMU_0x01) << GBEMU_8) | (parentObj.romBank1offs & GBEMU_0xFF);
    parentObj.setCurrentMBC5romBank();
  }
  mBC5WriteRAMBank(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC5 RAM bank switching
    parentObj.currMBCRAMBank = data & GBEMU_0xF;
    parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
  }
  rUMBLEWriteRAMBank(parentObj: GameBoyCore, address: number, data: number): void {
    //MBC5 RAM bank switching
    //Like MBC5, but bit GBEMU_3 of the lower nibble is used for rumbling and bit GBEMU_2 is ignored.
    parentObj.currMBCRAMBank = data & GBEMU_0x03;
    parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
  }
  huC3WriteRAMBank(parentObj: GameBoyCore, address: number, data: number): void {
    //HuC3 RAM bank switching
    parentObj.currMBCRAMBank = data & GBEMU_0x03;
    parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
  }
  cartIgnoreWrite(parentObj: GameBoyCore, address: number, data: number): void {
    //We might have encountered illegal RAM writing or such, so just do nothing...
  }
  memoryWriteNormal(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj.memory[address] = data;
  }
  memoryHighWriteNormal(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj.memory[GBEMU_0xFF00 | address] = data;
  }
  memoryWriteMBCRAM(parentObj: GameBoyCore, address: number, data: number): void {
    if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
      parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition] = data;
    }
  }
  memoryWriteMBC3RAM(parentObj: GameBoyCore, address: number, data: number): void {
    //debugLog('This is memoryWriteMBC3RAM');
    if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
      switch (parentObj.currMBCRAMBank) {
        case GBEMU_0x00:
        case GBEMU_0x01:
        case GBEMU_0x02:
        case GBEMU_0x03:
          parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition] = data;
          break;
        case GBEMU_0x08:
          if (data < GBEMU_60) {
            parentObj.rtcSeconds = data;
          } else {
            cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
          }
          break;
        case GBEMU_0x09:
          if (data < GBEMU_60) {
            parentObj.rtcMinutes = data;
          } else {
            cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
          }
          break;
        case GBEMU_0x0A:
          if (data < GBEMU_24) {
            parentObj.rtcHours = data;
          } else {
            cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
          }
          break;
        case GBEMU_0x0B:
          parentObj.rtcDays = (data & GBEMU_0xFF) | (parentObj.rtcDays & GBEMU_0x100);
          break;
        case GBEMU_0x0C:
          parentObj.rtcDayOverFlow = data > GBEMU_0x7F;
          parentObj.rtcHalt = (data & GBEMU_0x40) === GBEMU_0x40;
          parentObj.rtcDays = ((data & GBEMU_0x1) << GBEMU_8) | (parentObj.rtcDays & GBEMU_0xFF);
          break;
        default:
          cout('Invalid MBC3 bank address selected: ' + parentObj.currMBCRAMBank, 0);
      }
    }
  }
  memoryWriteGBCRAM(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj.gbcMemory![address + parentObj.gbcRamBankPosition] = data;
  }
  memoryWriteOAMRAM(parentObj: GameBoyCore, address: number, data: number): void {
    if (parentObj.modeSTAT < GBEMU_2) {
      //OAM RAM cannot be written to in mode GBEMU_2 & GBEMU_3
      if (parentObj.memory[address] !== data) {
        parentObj.graphicsJIT();
        parentObj.memory[address] = data;
      }
    }
  }
  memoryWriteECHOGBCRAM(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj!.gbcMemory![address + parentObj!.gbcRamBankPositionECHO] = data;
  }
  memoryWriteECHONormal(parentObj: GameBoyCore, address: number, data: number): void {
    parentObj.memory[address - GBEMU_0x2000] = data;
  }
  vRAMGBDATAWrite(parentObj: GameBoyCore, address: number, data: number): void {
    if (parentObj.modeSTAT < GBEMU_3) {
      //vram cannot be written to during mode GBEMU_3
      if (parentObj.memory[address] !== data) {
        //JIT the graphics render queue:
        parentObj.graphicsJIT();
        parentObj.memory[address] = data;
        parentObj.generateGBOAMTileLine(address);
      }
    }
  }
  vRAMGBDATAUpperWrite(parentObj: GameBoyCore, address: number, data: number): void {
    if (parentObj.modeSTAT < GBEMU_3) {
      //vram cannot be written to during mode GBEMU_3
      if (parentObj.memory[address] !== data) {
        //JIT the graphics render queue:
        parentObj.graphicsJIT();
        parentObj.memory[address] = data;
        parentObj.generateGBTileLine(address);
      }
    }
  }
  vRAMGBCDATAWrite(parentObj: GameBoyCore, addressTemp: number, data: number): void {
    let address = addressTemp;
    if (parentObj.modeSTAT < GBEMU_3) {
      //vram cannot be written to during mode GBEMU_3
      if (parentObj.currvramBank === GBEMU_0) {
        if (parentObj.memory[address] !== data) {
          parentObj.graphicsJIT(); //JIT the graphics render queue
          parentObj.memory[address] = data;
          parentObj.generateGBCTileLineBank1(address);
        }
      } else {
        address &= GBEMU_0x1FFF;
        if (parentObj.vram![address] != data) {
          //JIT the graphics render queue:
          parentObj.graphicsJIT();
          parentObj!.vram![address] = data;
          parentObj.generateGBCTileLineBank2(address);
        }
      }
    }
  }
  vRAMGBCHRMAPWrite(parentObj: GameBoyCore, addressTemp: number, data: number): void {
    let address = addressTemp;
    if (parentObj.modeSTAT < GBEMU_3) {
      //vram cannot be written to during mode GBEMU_3
      address &= GBEMU_0x7FF;
      if (parentObj.bgCHRBank1.array[address] !== data) {
        //JIT the graphics render queue:
        parentObj.graphicsJIT();
        parentObj.bgCHRBank1.array[address] = data;
      }
    }
  }
  vRAMGBCCHRMAPWrite(parentObj: GameBoyCore, tempAddress: number, data: number): void {
    let address = tempAddress;
    if (parentObj.modeSTAT < GBEMU_3) {
      //vram cannot be written to during mode GBEMU_3
      address &= GBEMU_0x7FF;
      if (parentObj!.bgCHRCurrentBank!.array[address] !== data) {
        //JIT the graphics render queue:
        parentObj.graphicsJIT();
        parentObj!.bgCHRCurrentBank!.array[address] = data;
      }
    }
  }
  dMAWrite(tilesToTransferTemp: number): void {
    let tilesToTransfer = tilesToTransferTemp;
    if (!this.halt) {
      //Clock the CPU for the DMA transfer (CPU is halted during the transfer):
      this.cpuTicks += GBEMU_4 | ((tilesToTransfer << GBEMU_5) << this.doubleSpeedShifter);
    }
    //Source address of the transfer:
    let source: number = (this.memory[GBEMU_0xFF51] << GBEMU_8) | this.memory[GBEMU_0xFF52];
    //Destination address in the vram memory range:
    let destination: number = (this.memory[GBEMU_0xFF53] << GBEMU_8) | this.memory[GBEMU_0xFF54];
    //Creating some references:
    let memoryReader: Array<(parentObj: GameBoyCore, address: number) => number> = this.memoryReader;
    //JIT the graphics render queue:
    this.graphicsJIT();
    let memory: TNextArray = this.memory;
    //Determining which bank we're working on so we can optimize:
    if (this.currvramBank === 0) {
      //DMA transfer for vram bank 0:
      do {
        if (destination < GBEMU_0x1800) {
          memory[GBEMU_0x8000 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8001 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8002 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8003 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8004 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8005 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8006 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8007 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8008 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x8009 | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800A | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800B | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800C | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800D | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800E | destination] = memoryReader[source](this, source++);
          memory[GBEMU_0x800F | destination] = memoryReader[source](this, source++);
          this.generateGBCTileBank1(destination);
          destination += GBEMU_0x10;
        } else {
          destination &= GBEMU_0x7F0;
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
          destination = (destination + GBEMU_0x1800) & GBEMU_0x1FF0;
        }
        source &= GBEMU_0xFFF0;
        tilesToTransfer -= 1;
      } while (tilesToTransfer > 0);
    } else {
      let vram = this.vram;
      //DMA transfer for vram bank 1:
      do {
        if (destination < GBEMU_0x1800) {
          vram![destination] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x1] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x2] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x3] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x4] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x5] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x6] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x7] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x8] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0x9] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xA] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xB] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xC] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xD] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xE] = memoryReader[source](this, source++);
          vram![destination | GBEMU_0xF] = memoryReader[source](this, source++);
          this.generateGBCTileBank2(destination);
          destination += GBEMU_0x10;
        } else {
          destination &= GBEMU_0x7F0;
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
          destination = (destination + GBEMU_0x1800) & GBEMU_0x1FF0;
        }
        source &= GBEMU_0xFFF0;
        tilesToTransfer -= 1;
      } while (tilesToTransfer > 0);
    }
    //Update the HDMA registers to their next addresses:
    memory[GBEMU_0xFF51] = source >> GBEMU_8;
    memory[GBEMU_0xFF52] = source & GBEMU_0xF0;
    memory[GBEMU_0xFF53] = destination >> GBEMU_8;
    memory[GBEMU_0xFF54] = destination & GBEMU_0xF0;
  }
  registerWriteJumpCompile(): void {
    //debugLog('This is registerWriteJumpCompile');
    //I/O Registers (GB + GBC):
    //joyPad
    this.memoryWriter[GBEMU_0xFF00] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF00] =
        (data & GBEMU_0x30) |
        (((data & GBEMU_0x20) === 0 ? parentObj.joyPad >> GBEMU_4 : GBEMU_0xF) & ((data & GBEMU_0x10) === 0 ? parentObj.joyPad & GBEMU_0xF : GBEMU_0xF));
    };
    this.memoryHighWriter[0] = this.memoryWriter[GBEMU_0xFF00];
    //SB (Serial Transfer Data)
    this.memoryWriter[GBEMU_0xFF01] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.memory[GBEMU_0xFF02] < GBEMU_0x80) {
        //Cannot write while a serial transfer is active.
        parentObj.memory[GBEMU_0xFF01] = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x1] = this.memoryWriter[GBEMU_0xFF01];
    //DIV
    this.memoryWriter[GBEMU_0xFF04] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.divTicks &= GBEMU_0xFF; //Update DIV for realignment.
      parentObj.memory[GBEMU_0xFF04] = 0;
    };
    this.memoryHighWriter[GBEMU_0x4] = this.memoryWriter[GBEMU_0xFF04];
    //TIMA
    this.memoryWriter[GBEMU_0xFF05] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF05] = data;
    };
    this.memoryHighWriter[GBEMU_0x5] = this.memoryWriter[GBEMU_0xFF05];
    //TMA
    this.memoryWriter[GBEMU_0xFF06] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF06] = data;
    };
    this.memoryHighWriter[GBEMU_0x6] = this.memoryWriter[GBEMU_0xFF06];
    //TAC
    this.memoryWriter[GBEMU_0xFF07] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF07] = data & GBEMU_0x07;
      parentObj.timaEnabled = (data & GBEMU_0x04) === GBEMU_0x04;
      parentObj.tacClocker = Math.pow(GBEMU_4, (data & GBEMU_0x3) !== 0 ? data & GBEMU_0x3 : GBEMU_4) << GBEMU_2; //TODO: Find a way to not make a conditional in here...
    };
    this.memoryHighWriter[GBEMU_0x7] = this.memoryWriter[GBEMU_0xFF07];
    //IF (Interrupt Request)
    this.memoryWriter[GBEMU_0xFF0F] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.interruptsRequested = data;
      parentObj.checkIRQMatching();
    };
    this.memoryHighWriter[GBEMU_0xF] = this.memoryWriter[GBEMU_0xFF0F];
    this.memoryWriter[GBEMU_0xFF10] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (parentObj.channel1decreaseSweep && (data & GBEMU_0x08) === 0) {
          if (parentObj.channel1numSweep !== parentObj.channel1frequencySweepDivider) {
            parentObj.channel1SweepFault = true;
          }
        }
        parentObj.channel1lastTimeSweep = (data & GBEMU_0x70) >> GBEMU_4;
        parentObj.channel1frequencySweepDivider = data & GBEMU_0x07;
        parentObj.channel1decreaseSweep = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF10] = data;
        parentObj.channel1EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x10] = this.memoryWriter[GBEMU_0xFF10];
    this.memoryWriter[GBEMU_0xFF11] = (parentObj: GameBoyCore, address: number, tempData: number) => {
      let data = tempData;
      if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
        if (parentObj.soundMasterEnabled) {
          parentObj.audioJIT();
        } else {
          data &= GBEMU_0x3F;
        }
        parentObj.channel1CachedDuty = parentObj.dutyLookup[data >> GBEMU_6];
        parentObj.channel1totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
        parentObj.memory[GBEMU_0xFF11] = data & GBEMU_0xC0;
        parentObj.channel1EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x11] = this.memoryWriter[GBEMU_0xFF11];
    this.memoryWriter[GBEMU_0xFF12] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (parentObj.channel1Enabled && parentObj.channel1envelopeSweeps === 0) {
          //Zombie Volume PAPU Bug:
          if (((parentObj.memory[GBEMU_0xFF12] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
            if ((parentObj.memory[GBEMU_0xFF12] & GBEMU_0x8) === 0) {
              (parentObj.memory[GBEMU_0xFF12] & GBEMU_0x7) === GBEMU_0x7 ?
                  (parentObj.channel1envelopeVolume += GBEMU_2) :
                  (parentObj.channel1envelopeVolume += 1);
            }
            parentObj.channel1envelopeVolume = (GBEMU_16 - parentObj.channel1envelopeVolume) & GBEMU_0xF;
          } else if ((parentObj.memory[GBEMU_0xFF12] & GBEMU_0xF) === GBEMU_0x8) {
            parentObj.channel1envelopeVolume = (1 + parentObj.channel1envelopeVolume) & GBEMU_0xF;
          }
          parentObj.channel1OutputLevelCache();
        }
        parentObj.channel1envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF12] = data;
        parentObj.channel1VolumeEnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x12] = this.memoryWriter[GBEMU_0xFF12];
    this.memoryWriter[GBEMU_0xFF13] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.channel1frequency = (parentObj.channel1frequency & GBEMU_0x700) | data;
        parentObj.channel1FrequencyTracker = (GBEMU_0x800 - parentObj.channel1frequency) << GBEMU_2;
        parentObj.memory[GBEMU_0xFF13] = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x13] = this.memoryWriter[GBEMU_0xFF13];
    this.memoryWriter[GBEMU_0xFF14] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.channel1consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
        parentObj.channel1frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel1frequency & GBEMU_0xFF);
        parentObj.channel1FrequencyTracker = (GBEMU_0x800 - parentObj.channel1frequency) << GBEMU_2;
        if (data > GBEMU_0x7F) {
          //Reload GBEMU_0xFF10:
          parentObj.channel1timeSweep = parentObj.channel1lastTimeSweep;
          parentObj.channel1numSweep = parentObj.channel1frequencySweepDivider;
          //Reload GBEMU_0xFF12:
          let nr12 = parentObj.memory[GBEMU_0xFF12];
          parentObj.channel1envelopeVolume = nr12 >> GBEMU_4;
          parentObj.channel1OutputLevelCache();
          parentObj.channel1envelopeSweepsLast = (nr12 & GBEMU_0x7) - 1;
          if (parentObj.channel1totalLength === 0) {
            parentObj.channel1totalLength = GBEMU_0x40;
          }
          if (parentObj.channel1lastTimeSweep > 0 || parentObj.channel1frequencySweepDivider > 0) {
            parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x1;
          } else {
            parentObj.memory[GBEMU_0xFF26] &= GBEMU_0xFE;
          }
          if ((data & GBEMU_0x40) === GBEMU_0x40) {
            parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x1;
          }
          parentObj.channel1ShadowFrequency = parentObj.channel1frequency;
          //Reset frequency overflow check + frequency sweep type check:
          parentObj.channel1SweepFault = false;
          parentObj.runAudioSweep(); //Supposed to run immediately
        }
        parentObj.channel1EnableCheck();
        parentObj.memory[GBEMU_0xFF14] = data & GBEMU_0x40;
      }
    };
    this.memoryHighWriter[GBEMU_0x14] = this.memoryWriter[GBEMU_0xFF14];
    this.memoryWriter[GBEMU_0xFF16] = (parentObj: GameBoyCore, address: number, tempData: number) => {
      let data = tempData;
      if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
        if (parentObj.soundMasterEnabled) {
          parentObj.audioJIT();
        } else {
          data &= GBEMU_0x3F;
        }
        parentObj.channel2CachedDuty = parentObj.dutyLookup[data >> GBEMU_6];
        parentObj.channel2totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
        parentObj.memory[GBEMU_0xFF16] = data & GBEMU_0xC0;
        parentObj.channel2EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x16] = this.memoryWriter[GBEMU_0xFF16];
    this.memoryWriter[GBEMU_0xFF17] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (parentObj.channel2Enabled && parentObj.channel2envelopeSweeps === 0) {
          //Zombie Volume PAPU Bug:
          if (((parentObj.memory[GBEMU_0xFF17] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
            if ((parentObj.memory[GBEMU_0xFF17] & GBEMU_0x8) === 0) {
              (parentObj.memory[GBEMU_0xFF17] & GBEMU_0x7) === GBEMU_0x7 ?
                  (parentObj.channel2envelopeVolume += GBEMU_2) :
                  (parentObj.channel2envelopeVolume += 1);
            }
            parentObj.channel2envelopeVolume = (GBEMU_16 - parentObj.channel2envelopeVolume) & GBEMU_0xF;
          } else if ((parentObj.memory[GBEMU_0xFF17] & GBEMU_0xF) === GBEMU_0x8) {
            parentObj.channel2envelopeVolume = (1 + parentObj.channel2envelopeVolume) & GBEMU_0xF;
          }
          parentObj.channel2OutputLevelCache();
        }
        parentObj.channel2envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF17] = data;
        parentObj.channel2VolumeEnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x17] = this.memoryWriter[GBEMU_0xFF17];
    this.memoryWriter[GBEMU_0xFF18] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.channel2frequency = (parentObj.channel2frequency & GBEMU_0x700) | data;
        parentObj.channel2FrequencyTracker = (GBEMU_0x800 - parentObj.channel2frequency) << GBEMU_2;
        parentObj.memory[GBEMU_0xFF18] = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x18] = this.memoryWriter[GBEMU_0xFF18];
    this.memoryWriter[GBEMU_0xFF19] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (data > GBEMU_0x7F) {
          //Reload GBEMU_0xFF17:
          let nr22 = parentObj.memory[GBEMU_0xFF17];
          parentObj.channel2envelopeVolume = nr22 >> GBEMU_4;
          parentObj.channel2OutputLevelCache();
          parentObj.channel2envelopeSweepsLast = (nr22 & GBEMU_0x7) - 1;
          if (parentObj.channel2totalLength === 0) {
            parentObj.channel2totalLength = GBEMU_0x40;
          }
          if ((data & GBEMU_0x40) === GBEMU_0x40) {
            parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x2;
          }
        }
        parentObj.channel2consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
        parentObj.channel2frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel2frequency & GBEMU_0xFF);
        parentObj.channel2FrequencyTracker = (GBEMU_0x800 - parentObj.channel2frequency) << GBEMU_2;
        parentObj.memory[GBEMU_0xFF19] = data & GBEMU_0x40;
        parentObj.channel2EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x19] = this.memoryWriter[GBEMU_0xFF19];
    this.memoryWriter[GBEMU_0xFF1A] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (!parentObj.channel3canPlay && data >= GBEMU_0x80) {
          parentObj.channel3lastSampleLookup = 0;
          parentObj.channel3UpdateCache();
        }
        parentObj.channel3canPlay = data > GBEMU_0x7F;
        if (parentObj.channel3canPlay && parentObj.memory[GBEMU_0xFF1A] > GBEMU_0x7F && !parentObj.channel3consecutive) {
          parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x4;
        }
        parentObj.memory[GBEMU_0xFF1A] = data & GBEMU_0x80;
        //parentObj.channel3EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x1A] = this.memoryWriter[GBEMU_0xFF1A];
    this.memoryWriter[GBEMU_0xFF1B] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
        if (parentObj.soundMasterEnabled) {
          parentObj.audioJIT();
        }
        parentObj.channel3totalLength = GBEMU_0x100 - data;
        parentObj.memory[GBEMU_0xFF1B] = data;
        parentObj.channel3EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x1B] = this.memoryWriter[GBEMU_0xFF1B];
    this.memoryWriter[GBEMU_0xFF1C] = (parentObj: GameBoyCore, address: number, tempData: number) => {
      let data = tempData;
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        data &= GBEMU_0x60;
        parentObj.memory[GBEMU_0xFF1C] = data;
        parentObj.channel3patternType = data === 0 ? GBEMU_4 : (data >> GBEMU_5) - 1;
      }
    };
    this.memoryHighWriter[GBEMU_0x1C] = this.memoryWriter[GBEMU_0xFF1C];
    this.memoryWriter[GBEMU_0xFF1D] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.channel3frequency = (parentObj.channel3frequency & GBEMU_0x700) | data;
        parentObj.channel3FrequencyPeriod = (GBEMU_0x800 - parentObj.channel3frequency) << 1;
        parentObj.memory[GBEMU_0xFF1D] = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x1D] = this.memoryWriter[GBEMU_0xFF1D];
    this.memoryWriter[GBEMU_0xFF1E] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (data > GBEMU_0x7F) {
          if (parentObj.channel3totalLength === 0) {
            parentObj.channel3totalLength = GBEMU_0x100;
          }
          parentObj.channel3lastSampleLookup = 0;
          if ((data & GBEMU_0x40) === GBEMU_0x40) {
            parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x4;
          }
        }
        parentObj.channel3consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
        parentObj.channel3frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel3frequency & GBEMU_0xFF);
        parentObj.channel3FrequencyPeriod = (GBEMU_0x800 - parentObj.channel3frequency) << 1;
        parentObj.memory[GBEMU_0xFF1E] = data & GBEMU_0x40;
        parentObj.channel3EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x1E] = this.memoryWriter[GBEMU_0xFF1E];
    this.memoryWriter[GBEMU_0xFF20] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
        if (parentObj.soundMasterEnabled) {
          parentObj.audioJIT();
        }
        parentObj.channel4totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
        parentObj.memory[GBEMU_0xFF20] = data | GBEMU_0xC0;
        parentObj.channel4EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x20] = this.memoryWriter[GBEMU_0xFF20];
    this.memoryWriter[GBEMU_0xFF21] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        if (parentObj.channel4Enabled && parentObj.channel4envelopeSweeps === 0) {
          //Zombie Volume PAPU Bug:
          if (((parentObj.memory[GBEMU_0xFF21] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
            if ((parentObj.memory[GBEMU_0xFF21] & GBEMU_0x8) === 0) {
              (parentObj.memory[GBEMU_0xFF21] & GBEMU_0x7) === GBEMU_0x7 ?
                  (parentObj.channel4envelopeVolume += GBEMU_2) :
                  (parentObj.channel4envelopeVolume += 1);
            }
            parentObj.channel4envelopeVolume = (GBEMU_16 - parentObj.channel4envelopeVolume) & GBEMU_0xF;
          } else if ((parentObj.memory[GBEMU_0xFF21] & GBEMU_0xF) === GBEMU_0x8) {
            parentObj.channel4envelopeVolume = (1 + parentObj.channel4envelopeVolume) & GBEMU_0xF;
          }
          parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
        }
        parentObj.channel4envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF21] = data;
        parentObj.channel4UpdateCache();
        parentObj.channel4VolumeEnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x21] = this.memoryWriter[GBEMU_0xFF21];
    this.memoryWriter[GBEMU_0xFF22] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.channel4FrequencyPeriod = Math.max((data & GBEMU_0x7) << GBEMU_4, GBEMU_8) << (data >> GBEMU_4);
        let bitWidth = data & GBEMU_0x8;
        if ((bitWidth === GBEMU_0x8 && parentObj.channel4BitRange === GBEMU_0x7FFF) || (bitWidth === 0 && parentObj.channel4BitRange === GBEMU_0x7F)) {
          parentObj.channel4lastSampleLookup = 0;
          parentObj.channel4BitRange = bitWidth === GBEMU_0x8 ? GBEMU_0x7F : GBEMU_0x7FFF;
          parentObj.channel4VolumeShifter = bitWidth === GBEMU_0x8 ? GBEMU_7 : GBEMU_15;
          parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
          parentObj.noiseSampleTable = bitWidth === GBEMU_0x8 ? parentObj.lsfr7Table : parentObj.lsfr15Table;
        }
        parentObj.memory[GBEMU_0xFF22] = data;
        parentObj.channel4UpdateCache();
      }
    };
    this.memoryHighWriter[GBEMU_0x22] = this.memoryWriter[GBEMU_0xFF22];
    this.memoryWriter[GBEMU_0xFF23] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled) {
        parentObj.audioJIT();
        parentObj.memory[GBEMU_0xFF23] = data;
        parentObj.channel4consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
        if (data > GBEMU_0x7F) {
          let nr42 = parentObj.memory[GBEMU_0xFF21];
          parentObj.channel4envelopeVolume = nr42 >> GBEMU_4;
          parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
          parentObj.channel4envelopeSweepsLast = (nr42 & GBEMU_0x7) - 1;
          if (parentObj.channel4totalLength === 0) {
            parentObj.channel4totalLength = GBEMU_0x40;
          }
          if ((data & GBEMU_0x40) === GBEMU_0x40) {
            parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x8;
          }
        }
        parentObj.channel4EnableCheck();
      }
    };
    this.memoryHighWriter[GBEMU_0x23] = this.memoryWriter[GBEMU_0xFF23];
    this.memoryWriter[GBEMU_0xFF24] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled && parentObj.memory[GBEMU_0xFF24] !== data) {
        parentObj.audioJIT();
        parentObj.memory[GBEMU_0xFF24] = data;
        parentObj.vinLeftChannelMasterVolume = ((data >> GBEMU_4) & GBEMU_0x07) + 1;
        parentObj.vinRightChannelMasterVolume = (data & GBEMU_0x07) + 1;
        parentObj.mixerOutputLevelCache();
      }
    };
    this.memoryHighWriter[GBEMU_0x24] = this.memoryWriter[GBEMU_0xFF24];
    this.memoryWriter[GBEMU_0xFF25] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.soundMasterEnabled && parentObj.memory[GBEMU_0xFF25] !== data) {
        parentObj.audioJIT();
        parentObj.memory[GBEMU_0xFF25] = data;
        parentObj.rightChannel1 = (data & GBEMU_0x01) === GBEMU_0x01;
        parentObj.rightChannel2 = (data & GBEMU_0x02) === GBEMU_0x02;
        parentObj.rightChannel3 = (data & GBEMU_0x04) === GBEMU_0x04;
        parentObj.rightChannel4 = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.leftChannel1 = (data & GBEMU_0x10) === GBEMU_0x10;
        parentObj.leftChannel2 = (data & GBEMU_0x20) === GBEMU_0x20;
        parentObj.leftChannel3 = (data & GBEMU_0x40) === GBEMU_0x40;
        parentObj.leftChannel4 = data > GBEMU_0x7F;
        parentObj.channel1OutputLevelCache();
        parentObj.channel2OutputLevelCache();
        parentObj.channel3OutputLevelCache();
        parentObj.channel4OutputLevelCache();
      }
    };
    this.memoryHighWriter[GBEMU_0x25] = this.memoryWriter[GBEMU_0xFF25];
    this.memoryWriter[GBEMU_0xFF26] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.audioJIT();
      if (!parentObj.soundMasterEnabled && data > GBEMU_0x7F) {
        parentObj.memory[GBEMU_0xFF26] = GBEMU_0x80;
        parentObj.soundMasterEnabled = true;
        parentObj.initializeAudioStartState();
      } else if (parentObj.soundMasterEnabled && data < GBEMU_0x80) {
        parentObj.memory[GBEMU_0xFF26] = 0;
        parentObj.soundMasterEnabled = false;
        //GBDev wiki says the registers are written with zeros on power off:
        for (let index = GBEMU_0xFF10; index < GBEMU_0xFF26; index++) {
          parentObj.memoryWriter[index](parentObj, index, 0);
        }
      }
    };
    this.memoryHighWriter[GBEMU_0x26] = this.memoryWriter[GBEMU_0xFF26];
    //GBEMU_0xFF27 to GBEMU_0xFF2F don't do anything...
    this.memoryHighWriter[GBEMU_0x27] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF27] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x28] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF28] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x29] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF29] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2A] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2A] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2B] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2B] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2C] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2C] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2D] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2D] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2E] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2E] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x2F] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF2F] = this.cartIgnoreWrite;
    //WAVE PCM RAM:
    this.memoryWriter[GBEMU_0xFF30] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(0, data);
    };
    this.memoryHighWriter[GBEMU_0x30] = this.memoryWriter[GBEMU_0xFF30];
    this.memoryWriter[GBEMU_0xFF31] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x1, data);
    };
    this.memoryHighWriter[GBEMU_0x31] = this.memoryWriter[GBEMU_0xFF31];
    this.memoryWriter[GBEMU_0xFF32] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x2, data);
    };
    this.memoryHighWriter[GBEMU_0x32] = this.memoryWriter[GBEMU_0xFF32];
    this.memoryWriter[GBEMU_0xFF33] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x3, data);
    };
    this.memoryHighWriter[GBEMU_0x33] = this.memoryWriter[GBEMU_0xFF33];
    this.memoryWriter[GBEMU_0xFF34] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x4, data);
    };
    this.memoryHighWriter[GBEMU_0x34] = this.memoryWriter[GBEMU_0xFF34];
    this.memoryWriter[GBEMU_0xFF35] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x5, data);
    };
    this.memoryHighWriter[GBEMU_0x35] = this.memoryWriter[GBEMU_0xFF35];
    this.memoryWriter[GBEMU_0xFF36] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x6, data);
    };
    this.memoryHighWriter[GBEMU_0x36] = this.memoryWriter[GBEMU_0xFF36];
    this.memoryWriter[GBEMU_0xFF37] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x7, data);
    };
    this.memoryHighWriter[GBEMU_0x37] = this.memoryWriter[GBEMU_0xFF37];
    this.memoryWriter[GBEMU_0xFF38] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x8, data);
    };
    this.memoryHighWriter[GBEMU_0x38] = this.memoryWriter[GBEMU_0xFF38];
    this.memoryWriter[GBEMU_0xFF39] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0x9, data);
    };
    this.memoryHighWriter[GBEMU_0x39] = this.memoryWriter[GBEMU_0xFF39];
    this.memoryWriter[GBEMU_0xFF3A] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xA, data);
    };
    this.memoryHighWriter[GBEMU_0x3A] = this.memoryWriter[GBEMU_0xFF3A];
    this.memoryWriter[GBEMU_0xFF3B] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xB, data);
    };
    this.memoryHighWriter[GBEMU_0x3B] = this.memoryWriter[GBEMU_0xFF3B];
    this.memoryWriter[GBEMU_0xFF3C] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xC, data);
    };
    this.memoryHighWriter[GBEMU_0x3C] = this.memoryWriter[GBEMU_0xFF3C];
    this.memoryWriter[GBEMU_0xFF3D] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xD, data);
    };
    this.memoryHighWriter[GBEMU_0x3D] = this.memoryWriter[GBEMU_0xFF3D];
    this.memoryWriter[GBEMU_0xFF3E] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xE, data);
    };
    this.memoryHighWriter[GBEMU_0x3E] = this.memoryWriter[GBEMU_0xFF3E];
    this.memoryWriter[GBEMU_0xFF3F] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.channel3WriteRAM(GBEMU_0xF, data);
    };
    this.memoryHighWriter[GBEMU_0x3F] = this.memoryWriter[GBEMU_0xFF3F];
    //SCY
    this.memoryWriter[GBEMU_0xFF42] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.backgroundY !== data) {
        parentObj.midScanLineJIT();
        parentObj.backgroundY = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x42] = this.memoryWriter[GBEMU_0xFF42];
    //SCX
    this.memoryWriter[GBEMU_0xFF43] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.backgroundX !== data) {
        parentObj.midScanLineJIT();
        parentObj.backgroundX = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x43] = this.memoryWriter[GBEMU_0xFF43];
    //LY
    this.memoryWriter[GBEMU_0xFF44] = (parentObj: GameBoyCore, address: number, data: number) => {
      //Read Only:
      if (parentObj.lcdIsOn) {
        //Gambatte says to do this:
        parentObj.modeSTAT = GBEMU_2;
        parentObj.midScanlineOffset = -1;
        parentObj.totalLinesPassed = 0;
        parentObj.currentX = 0;
        parentObj.queuedScanLines = 0;
        parentObj.lastUnrenderedLine = 0;
        parentObj.lcdTicks = 0;
        parentObj.statTracker = 0;
        parentObj.actualScanLine = 0;
        parentObj.memory[GBEMU_0xFF44] = 0;
      }
    };
    this.memoryHighWriter[GBEMU_0x44] = this.memoryWriter[GBEMU_0xFF44];
    //LYC
    this.memoryWriter[GBEMU_0xFF45] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.memory[GBEMU_0xFF45] !== data) {
        parentObj.memory[GBEMU_0xFF45] = data;
        if (parentObj.lcdIsOn) {
          parentObj.matchLYC(); //Get the compare of the first scan line.
        }
      }
    };
    this.memoryHighWriter[GBEMU_0x45] = this.memoryWriter[GBEMU_0xFF45];
    //WY
    this.memoryWriter[GBEMU_0xFF4A] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.windowY !== data) {
        parentObj.midScanLineJIT();
        parentObj.windowY = data;
      }
    };
    this.memoryHighWriter[GBEMU_0x4A] = this.memoryWriter[GBEMU_0xFF4A];
    //WX
    this.memoryWriter[GBEMU_0xFF4B] = (parentObj: GameBoyCore, address: number, data: number) => {
      if (parentObj.memory[GBEMU_0xFF4B] !== data) {
        parentObj.midScanLineJIT();
        parentObj.memory[GBEMU_0xFF4B] = data;
        parentObj.windowX = data - GBEMU_7;
      }
    };
    this.memoryHighWriter[GBEMU_0x4B] = this.memoryWriter[GBEMU_0xFF4B];
    this.memoryWriter[GBEMU_0xFF72] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF72] = data;
    };
    this.memoryHighWriter[GBEMU_0x72] = this.memoryWriter[GBEMU_0xFF72];
    this.memoryWriter[GBEMU_0xFF73] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF73] = data;
    };
    this.memoryHighWriter[GBEMU_0x73] = this.memoryWriter[GBEMU_0xFF73];
    this.memoryWriter[GBEMU_0xFF75] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.memory[GBEMU_0xFF75] = data;
    };
    this.memoryHighWriter[GBEMU_0x75] = this.memoryWriter[GBEMU_0xFF75];
    this.memoryHighWriter[GBEMU_0x76] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF76] = this.cartIgnoreWrite;
    this.memoryHighWriter[GBEMU_0x77] = this.cartIgnoreWrite;
    this.memoryWriter[GBEMU_0xFF77] = this.cartIgnoreWrite;
    //IE (Interrupt Enable)
    this.memoryWriter[GBEMU_0xFFFF] = (parentObj: GameBoyCore, address: number, data: number) => {
      parentObj.interruptsEnabled = data;
      parentObj.checkIRQMatching();
    };
    this.memoryHighWriter[GBEMU_0xFF] = this.memoryWriter[GBEMU_0xFFFF];
    this.recompileModelSpecificIOWriteHandling();
    this.recompileBootIOWriteHandling();
  }

  recompileModelSpecificIOWriteHandling(): void {
    //debugLog('This is recompileModelSpecificIOWriteHandling');
    if (this.cGBC) {
      //GameBoy Color Specific I/O:
      //SC (Serial Transfer Control Register)
      this.memoryWriter[GBEMU_0xFF02] = (parentObj: GameBoyCore, address: number, data: number) => {
        if ((data & GBEMU_0x1) === GBEMU_0x1) {
          //Internal clock:
          parentObj.memory[GBEMU_0xFF02] = data & GBEMU_0x7F;
          parentObj.serialTimer = (data & GBEMU_0x2) === 0 ? GBEMU_4096 : GBEMU_128; //Set the Serial IRQ counter.
          parentObj.serialShiftTimer = (data & GBEMU_0x2) === 0 ? GBEMU_512 : GBEMU_16; //Set the transfer data shift counter.
          parentObj.serialShiftTimerAllocated = parentObj.serialShiftTimer;
        } else {
          //External clock:
          parentObj.memory[GBEMU_0xFF02] = data;
          parentObj.serialShiftTimer = 0; //Zero the timers, since we're emulating as if nothing is connected.
          parentObj.serialShiftTimerAllocated = parentObj.serialShiftTimer;
          parentObj.serialTimer = parentObj.serialShiftTimer;
        }
      };
      this.memoryHighWriter[GBEMU_0x2] = this.memoryWriter[GBEMU_0xFF02];
      this.memoryWriter[GBEMU_0xFF40] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (parentObj.memory[GBEMU_0xFF40] !== data) {
          parentObj.midScanLineJIT();
          let tempVar = data > GBEMU_0x7F;
          if (tempVar !== parentObj.lcdIsOn) {
            //When the display mode changes...
            parentObj.lcdIsOn = tempVar;
            parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x78;
            parentObj.midScanlineOffset = -1;
            parentObj.totalLinesPassed = 0;
            parentObj.currentX = 0;
            parentObj.queuedScanLines = 0;
            parentObj.lastUnrenderedLine = 0;
            parentObj.statTracker = 0;
            parentObj.lcdTicks = 0;
            parentObj.actualScanLine = 0;
            parentObj.memory[GBEMU_0xFF44] = 0;
            if (parentObj.lcdIsOn) {
              parentObj.modeSTAT = GBEMU_2;
              parentObj.matchLYC(); //Get the compare of the first scan line.
              parentObj.lcdControl = parentObj.lineControl;
            } else {
              parentObj.modeSTAT = 0;
              parentObj.lcdControl = parentObj.disPlayOffControl;
              parentObj.displayShowOff();
            }
            parentObj.interruptsRequested &= GBEMU_0xFD;
          }
          parentObj.gfxWindowCHRBankPosition = (data & GBEMU_0x40) === GBEMU_0x40 ? GBEMU_0x400 : 0;
          parentObj.gfxWindowDisplay = (data & GBEMU_0x20) === GBEMU_0x20;
          parentObj.gfxBackgroundBankOffset = (data & GBEMU_0x10) === GBEMU_0x10 ? 0 : GBEMU_0x80;
          parentObj.gfxBackgroundCHRBankPosition = (data & GBEMU_0x08) === GBEMU_0x08 ? GBEMU_0x400 : 0;
          parentObj.gfxSpriteNormalHeight = (data & GBEMU_0x04) === 0;
          parentObj.gfxSpriteShow = (data & GBEMU_0x02) === GBEMU_0x02;
          parentObj.bgPriorityEnabled = (data & GBEMU_0x01) === GBEMU_0x01;
          parentObj.priorityFlaggingPathRebuild(); //Special case the priority flagging as an optimization.
          parentObj.memory[GBEMU_0xFF40] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x40] = this.memoryWriter[GBEMU_0xFF40];
      this.memoryWriter[GBEMU_0xFF41] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.lycMatchTriggerSTAT = (data & GBEMU_0x40) === GBEMU_0x40;
        parentObj.mode2TriggerSTAT = (data & GBEMU_0x20) === GBEMU_0x20;
        parentObj.mode1TriggerSTAT = (data & GBEMU_0x10) === GBEMU_0x10;
        parentObj.mode0TriggerSTAT = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF41] = data & GBEMU_0x78;
      };
      this.memoryHighWriter[GBEMU_0x41] = this.memoryWriter[GBEMU_0xFF41];
      this.memoryWriter[GBEMU_0xFF46] = (parentObj: GameBoyCore, addressTemp: number, dataTemp: number) => {
        let data = dataTemp;
        let address = addressTemp;
        parentObj.memory[GBEMU_0xFF46] = data;
        if (data < GBEMU_0xE0) {
          data <<= GBEMU_8;
          address = GBEMU_0xFE00;
          let stat = parentObj.modeSTAT;
          parentObj.modeSTAT = GBEMU_0;
          let newData = GBEMU_0;
          do {
            newData = parentObj.memoryReader[data](parentObj, data++);
            if (newData !== parentObj.memory[address]) {
              parentObj.modeSTAT = stat; //JIT the graphics render queue
              parentObj.graphicsJIT();
              parentObj.modeSTAT = GBEMU_0;
              parentObj.memory[address++] = newData;
              break;
            }
            address += 1;
          } while (address < GBEMU_0xFEA0);
          if (address < GBEMU_0xFEA0) {
            do {
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
            } while (address < GBEMU_0xFEA0);
          }
          parentObj.modeSTAT = stat;
        }
      };
      this.memoryHighWriter[GBEMU_0x46] = this.memoryWriter[GBEMU_0xFF46];
      //KEY1
      this.memoryWriter[GBEMU_0xFF4D] = (parentObj: GameBoyCore, address: number, data: number) => {
        let temp = parentObj.memory[GBEMU_0xFF4D] & GBEMU_0x80;
        parentObj.memory[GBEMU_0xFF4D] = (data & GBEMU_0x7F) | temp;
      };
      this.memoryHighWriter[GBEMU_0x4D] = this.memoryWriter[GBEMU_0xFF4D];
      this.memoryWriter[GBEMU_0xFF4F] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.currvramBank = data & GBEMU_0x01;
        if (parentObj.currvramBank > 0) {
          parentObj.bgCHRCurrentBank = parentObj.bgCHRBank2;
        } else {
          parentObj.bgCHRCurrentBank = parentObj.bgCHRBank1;
        }
        //Only writable by GBC.
      };
      this.memoryHighWriter[GBEMU_0x4F] = this.memoryWriter[GBEMU_0xFF4F];
      this.memoryWriter[GBEMU_0xFF51] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (!parentObj.hdmaRunning) {
          parentObj.memory[GBEMU_0xFF51] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x51] = this.memoryWriter[GBEMU_0xFF51];
      this.memoryWriter[GBEMU_0xFF52] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (!parentObj.hdmaRunning) {
          parentObj.memory[GBEMU_0xFF52] = data & GBEMU_0xF0;
        }
      };
      this.memoryHighWriter[GBEMU_0x52] = this.memoryWriter[GBEMU_0xFF52];
      this.memoryWriter[GBEMU_0xFF53] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (!parentObj.hdmaRunning) {
          parentObj.memory[GBEMU_0xFF53] = data & GBEMU_0x1F;
        }
      };
      this.memoryHighWriter[GBEMU_0x53] = this.memoryWriter[GBEMU_0xFF53];
      this.memoryWriter[GBEMU_0xFF54] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (!parentObj.hdmaRunning) {
          parentObj.memory[GBEMU_0xFF54] = data & GBEMU_0xF0;
        }
      };
      this.memoryHighWriter[GBEMU_0x54] = this.memoryWriter[GBEMU_0xFF54];
      this.memoryWriter[GBEMU_0xFF55] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (!parentObj.hdmaRunning) {
          if ((data & GBEMU_0x80) === 0) {
            //DMA
            parentObj.dMAWrite((data & GBEMU_0x7F) + 1);
            parentObj.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed.
          } else {
            //H-Blank DMA
            parentObj.hdmaRunning = true;
            parentObj.memory[GBEMU_0xFF55] = data & GBEMU_0x7F;
          }
        } else if ((data & GBEMU_0x80) === 0) {
          //Stop H-Blank DMA
          parentObj.hdmaRunning = false;
          parentObj.memory[GBEMU_0xFF55] |= GBEMU_0x80;
        } else {
          parentObj.memory[GBEMU_0xFF55] = data & GBEMU_0x7F;
        }
      };
      this.memoryHighWriter[GBEMU_0x55] = this.memoryWriter[GBEMU_0xFF55];
      this.memoryWriter[GBEMU_0xFF68] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.memory[GBEMU_0xFF69] = parentObj.gbcBGRawPalette![data & GBEMU_0x3F];
        parentObj.memory[GBEMU_0xFF68] = data;
      };
      this.memoryHighWriter[GBEMU_0x68] = this.memoryWriter[GBEMU_0xFF68];
      this.memoryWriter[GBEMU_0xFF69] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.updateGBCBGPalette(parentObj.memory[GBEMU_0xFF68] & GBEMU_0x3F, data);
        if (parentObj.memory[GBEMU_0xFF68] > GBEMU_0x7F) {
          // high bit = autoincrement
          let next = (parentObj.memory[GBEMU_0xFF68] + 1) & GBEMU_0x3F;
          parentObj.memory[GBEMU_0xFF68] = next | GBEMU_0x80;
          parentObj.memory[GBEMU_0xFF69] = parentObj.gbcBGRawPalette![next];
        } else {
          parentObj.memory[GBEMU_0xFF69] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x69] = this.memoryWriter[GBEMU_0xFF69];
      this.memoryWriter[GBEMU_0xFF6A] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.memory[GBEMU_0xFF6B] = parentObj.gbcOBJRawPalette![data & GBEMU_0x3F];
        parentObj.memory[GBEMU_0xFF6A] = data;
      };
      this.memoryHighWriter[GBEMU_0x6A] = this.memoryWriter[GBEMU_0xFF6A];
      this.memoryWriter[GBEMU_0xFF6B] = (parentObj: GameBoyCore, address: number, data: number) => {
        let temp = parentObj.memory[GBEMU_0xFF6A];
        parentObj.updateGBCOBJPalette(temp & GBEMU_0x3F, data);
        if (temp > GBEMU_0x7F) {
          // high bit = autoincrement
          let next = (parentObj.memory[GBEMU_0xFF6A] + 1) & GBEMU_0x3F;
          parentObj.memory[GBEMU_0xFF6A] = next | GBEMU_0x80;
          parentObj.memory[GBEMU_0xFF6B] = parentObj.gbcOBJRawPalette![next];
        } else {
          parentObj.memory[GBEMU_0xFF6B] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x6B] = this.memoryWriter[GBEMU_0xFF6B];
      //SVBK
      this.memoryWriter[GBEMU_0xFF70] = (parentObj: GameBoyCore, address: number, data: number) => {
        let addressCheck = (parentObj.memory[GBEMU_0xFF51] << GBEMU_8) | parentObj.memory[GBEMU_0xFF52]; //Cannot change the RAM bank while WRAM is the source of a running HDMA.
        if (!parentObj.hdmaRunning || addressCheck < GBEMU_0xD000 || addressCheck >= GBEMU_0xE000) {
          parentObj.gbcRamBank = Math.max(data & GBEMU_0x07, 1); //Bank range is from 1-GBEMU_7
          parentObj.gbcRamBankPosition = ((parentObj.gbcRamBank - 1) << GBEMU_12) - GBEMU_0xD000;
          parentObj.gbcRamBankPositionECHO = parentObj.gbcRamBankPosition - GBEMU_0x2000;
        }
        parentObj.memory[GBEMU_0xFF70] = data; //Bit GBEMU_6 cannot be written to.
      };
      this.memoryHighWriter[GBEMU_0x70] = this.memoryWriter[GBEMU_0xFF70];
      this.memoryWriter[GBEMU_0xFF74] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.memory[GBEMU_0xFF74] = data;
      };
      this.memoryHighWriter[GBEMU_0x74] = this.memoryWriter[GBEMU_0xFF74];
    } else {
      //Fill in the GameBoy Color I/O registers as normal RAM for GameBoy compatibility:
      //SC (Serial Transfer Control Register)
      this.memoryWriter[GBEMU_0xFF02] = (parentObj: GameBoyCore, address: number, data: number) => {
        if ((data & GBEMU_0x1) === GBEMU_0x1) {
          //Internal clock:
          parentObj.memory[GBEMU_0xFF02] = data & GBEMU_0x7F;
          parentObj.serialTimer = GBEMU_4096; //Set the Serial IRQ counter.
          parentObj.serialShiftTimer = GBEMU_512;
          parentObj.serialShiftTimerAllocated = GBEMU_512; //Set the transfer data shift counter.
        } else {
          //External clock:
          parentObj.memory[GBEMU_0xFF02] = data;
          parentObj.serialShiftTimer = 0;
          parentObj.serialShiftTimerAllocated = 0;
          parentObj.serialTimer = 0; //Zero the timers, since we're emulating as if nothing is connected.
        }
      };
      this.memoryHighWriter[GBEMU_0x2] = this.memoryWriter[GBEMU_0xFF02];
      this.memoryWriter[GBEMU_0xFF40] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (parentObj.memory[GBEMU_0xFF40] !== data) {
          parentObj.midScanLineJIT();
          let tempVar = data > GBEMU_0x7F;
          if (tempVar !== parentObj.lcdIsOn) {
            //When the display mode changes...
            parentObj.lcdIsOn = tempVar;
            parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x78;
            parentObj.midScanlineOffset = -1;
            parentObj.totalLinesPassed = 0;
            parentObj.currentX = 0;
            parentObj.queuedScanLines = 0;
            parentObj.lastUnrenderedLine = 0;
            parentObj.statTracker = 0;
            parentObj.lcdTicks = 0;
            parentObj.actualScanLine = 0;
            parentObj.memory[GBEMU_0xFF44] = 0;
            if (parentObj.lcdIsOn) {
              parentObj.modeSTAT = GBEMU_2;
              parentObj.matchLYC(); //Get the compare of the first scan line.
              parentObj.lcdControl = parentObj.lineControl;
            } else {
              parentObj.modeSTAT = 0;
              parentObj.lcdControl = parentObj.disPlayOffControl;
              parentObj.displayShowOff();
            }
            parentObj.interruptsRequested &= 0xfd;
          }
          parentObj.gfxWindowCHRBankPosition = (data & GBEMU_0x40) === GBEMU_0x40 ? GBEMU_0x400 : 0;
          parentObj.gfxWindowDisplay = (data & GBEMU_0x20) === GBEMU_0x20;
          parentObj.gfxBackgroundBankOffset = (data & GBEMU_0x10) === GBEMU_0x10 ? 0 : GBEMU_0x80;
          parentObj.gfxBackgroundCHRBankPosition = (data & GBEMU_0x08) === GBEMU_0x08 ? GBEMU_0x400 : 0;
          parentObj.gfxSpriteNormalHeight = (data & GBEMU_0x04) === 0;
          parentObj.gfxSpriteShow = (data & GBEMU_0x02) === GBEMU_0x02;
          parentObj.bgEnabled = (data & GBEMU_0x01) === GBEMU_0x01;
          parentObj.memory[GBEMU_0xFF40] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x40] = this.memoryWriter[GBEMU_0xFF40];
      this.memoryWriter[GBEMU_0xFF41] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.lycMatchTriggerSTAT = (data & GBEMU_0x40) === GBEMU_0x40;
        parentObj.mode2TriggerSTAT = (data & GBEMU_0x20) === GBEMU_0x20;
        parentObj.mode1TriggerSTAT = (data & GBEMU_0x10) === GBEMU_0x10;
        parentObj.mode0TriggerSTAT = (data & GBEMU_0x08) === GBEMU_0x08;
        parentObj.memory[GBEMU_0xFF41] = data & GBEMU_0x78;
        if ((!parentObj.usedBootrom || !parentObj.usedGBCBootrom) && parentObj.lcdIsOn && parentObj.modeSTAT < GBEMU_2) {
          parentObj.interruptsRequested |= GBEMU_0x2;
          parentObj.checkIRQMatching();
        }
      };
      this.memoryHighWriter[GBEMU_0x41] = this.memoryWriter[GBEMU_0xFF41];
      this.memoryWriter[GBEMU_0xFF46] = (parentObj: GameBoyCore, addressTemp: number, dataTemp: number) => {
        parentObj.memory[GBEMU_0xFF46] = dataTemp;
        let data = dataTemp;
        let address = addressTemp;
        if (data > GBEMU_0x7F && data < GBEMU_0xE0) {
          //DMG cannot DMA from the rom banks.
          data <<= GBEMU_8;
          address = GBEMU_0xFE00;
          let stat = parentObj.modeSTAT;
          parentObj.modeSTAT = 0;
          let newData = 0;
          do {
            newData = parentObj.memoryReader[data](parentObj, data++);
            if (newData !== parentObj.memory[address]) {
              //JIT the graphics render queue:
              parentObj.modeSTAT = stat;
              parentObj.graphicsJIT();
              parentObj.modeSTAT = 0;
              parentObj.memory[address++] = newData;
              break;
            }
            address += 1;
          } while (address < GBEMU_0xFEA0);
          if (address < GBEMU_0xFEA0) {
            do {
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
              parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
            } while (address < GBEMU_0xFEA0);
          }
          parentObj.modeSTAT = stat;
        }
      };
      this.memoryHighWriter[GBEMU_0x46] = this.memoryWriter[GBEMU_0xFF46];
      this.memoryWriter[GBEMU_0xFF47] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (parentObj.memory[GBEMU_0xFF47] !== data) {
          parentObj.midScanLineJIT();
          parentObj.updateGBBGPalette!(data);
          parentObj.memory[GBEMU_0xFF47] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x47] = this.memoryWriter[GBEMU_0xFF47];
      this.memoryWriter[GBEMU_0xFF48] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (parentObj.memory[GBEMU_0xFF48] !== data) {
          parentObj.midScanLineJIT();
          parentObj.updateGBOBJPalette!(0, data);
          parentObj.memory[GBEMU_0xFF48] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x48] = this.memoryWriter[GBEMU_0xFF48];
      this.memoryWriter[GBEMU_0xFF49] = (parentObj: GameBoyCore, address: number, data: number) => {
        if (parentObj.memory[GBEMU_0xFF49] !== data) {
          parentObj.midScanLineJIT();
          parentObj.updateGBOBJPalette!(GBEMU_4, data);
          parentObj.memory[GBEMU_0xFF49] = data;
        }
      };
      this.memoryHighWriter[GBEMU_0x49] = this.memoryWriter[GBEMU_0xFF49];
      this.memoryWriter[GBEMU_0xFF4D] = (parentObj: GameBoyCore, address: number, data: number) => {
        parentObj.memory[GBEMU_0xFF4D] = data;
      };
      this.memoryHighWriter[GBEMU_0x4D] = this.memoryWriter[GBEMU_0xFF4D];
      this.memoryHighWriter[GBEMU_0x4F] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF4F] = this.cartIgnoreWrite; //Not writable in DMG mode.
      this.memoryHighWriter[GBEMU_0x55] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF55] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x68] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF68] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x69] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF69] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x6A] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF6A] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x6B] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF6B] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x6C] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF6C] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x70] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF70] = this.cartIgnoreWrite;
      this.memoryHighWriter[GBEMU_0x74] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF74] = this.cartIgnoreWrite;
    }
  }

  recompileBootIOWriteHandling(): void {
    //debugLog('This is recompileBootIOWriteHandling');
    //Boot I/O Registers:
    if (this.inBootstrap) {
      this.memoryWriter[GBEMU_0xFF50] = (parentObj: GameBoyCore, address: number, data: number) => {
        //debugLog('Boot rom reads blocked: Bootstrap process has ended.')
        parentObj.inBootstrap = false;
        parentObj.disableBootrom();
        parentObj.memory[GBEMU_0xFF50] = data;
      };
      this.memoryHighWriter[GBEMU_0x50] = this.memoryWriter[GBEMU_0xFF50];
      if (this.cGBC) {
        this.memoryWriter[GBEMU_0xFF6C] = (parentObj: GameBoyCore, address: number, data: number) => {
          if (parentObj.inBootstrap) {
            parentObj.cGBC = (data & GBEMU_0x1) === 0;
            //Exception to the GBC identifying code:
            if (parentObj.name + parentObj.gameCode + parentObj.rom[GBEMU_0x143] === 'Game and Watch 50') {
              parentObj.cGBC = true;
              cout('Created a boot exception for Game and Watch Gallery GBEMU_2 (GBC ID byte is wrong on the cartridge).', 1);
            }
            cout('Booted to GBC Mode: ' + parentObj.cGBC, 0);
          }
          parentObj.memory[GBEMU_0xFF6C] = data;
        };
        this.memoryHighWriter[GBEMU_0x6C] = this.memoryWriter[GBEMU_0xFF6C];
      }
    } else {
      //Lockout the roms from accessing the BOOT rom control register:
      this.memoryHighWriter[GBEMU_0x50] = this.cartIgnoreWrite;
      this.memoryWriter[GBEMU_0xFF50] = this.cartIgnoreWrite;
    }
  }

  toTypedArray(baseArray: TNextArray, memtype: string): TNextArray {
    if (baseArray === null || baseArray.length === 0) {
      return new Int32Array();
    }
    let length = baseArray.length;
    let typedArrayTemp: TNextArray = new Uint8Array();
    switch (memtype) {
      case 'uint8':
        typedArrayTemp = new Uint8Array(length);
        break;
      case 'int8':
        typedArrayTemp = new Int8Array(length);
        break;
      case 'int32':
        typedArrayTemp = new Int32Array(length);
        break;
      case 'float32':
        typedArrayTemp = new Float32Array(length);
      default:
        break;
    }
    for (let index = 0; index < length; index++) {
      typedArrayTemp[index] = baseArray[index];
    }
    return typedArrayTemp;
  }

  fromTypedArray(baseArray: TNextArray): TNextArray {
    if (!baseArray || !baseArray.length) {
      return new Int8Array();
    }
    let arrayTemp: TNextArray = new Int8Array();
    for (let index = 0; index < baseArray.length; ++index) {
      arrayTemp[index] = baseArray[index];
    }
    return arrayTemp;
  }

  getTypedArray(length: number, defaultValue: number, numberType: string): TNextArray {
    let arrayHandle: TNextArray = new Int8Array();
    if (settings[GBEMU_5]) {
      for (let i = 0; i < length; i++) {
        arrayHandle[i] = defaultValue;
      }
      return arrayHandle;
    }
    switch (numberType) {
      case 'int8':
        arrayHandle = new Int8Array(length);
        break;
      case 'uint8':
        arrayHandle = new Uint8Array(length);
        break;
      case 'int32':
        arrayHandle = new Int32Array(length);
        break;
      case 'float32':
        arrayHandle = new Float32Array(length);
      default:
        break;
    }
    if (defaultValue !== 0) {
      let index = 0;
      while (index < length) {
        arrayHandle[index++] = defaultValue;
      }
    }
    return arrayHandle;
  }
}

// End of js/GameBoyCore.js file.

// Start of js/GameBoyIO.js file.

let gameboy: GameBoyCore | null = null;
let gbRunInterval: number | null = null; //GameBoyCore Timer
let settings: Array<boolean | number[] | number> = [
  //Some settings.
  true, //Turn on sound.
  false, //Boot with boot rom first? (set to false for benchmarking)
  false, //Give priority to GameBoy mode
  [GBEMU_39, GBEMU_37, GBEMU_38, GBEMU_40, GBEMU_88, GBEMU_90, GBEMU_16, GBEMU_13], //Keyboard button map.
  true, //Colorize GB mode?
  false, //Disallow typed arrays?
  GBEMU_4, //Interval for the emulator loop.
  GBEMU_15, //Audio buffer minimum span amount over x interpreter iterations.
  GBEMU_30, //Audio buffer maximum span amount over x interpreter iterations.
  false, //Override to allow for MBC1 instead of rom only (compatibility for broken 3rd-party cartridges).
  false, //Override MBC RAM disabling and always allow reading and writing to the banks.
  false, //Use the GameBoy boot rom instead of the GameBoy Color boot rom.
  false, //Scale the canvas in JS, or let the browser scale the canvas?
  GBEMU_0x10, //Internal audio buffer pre-interpolation factor.
  1 //Volume level set.
];

function start(canvas: GameBoyCanvas, rom: string): void {
  //debugLog('This is start');
  clearLastEmulation();
  gameboy = new GameBoyCore(canvas, rom);
  gameboy.openMBC = openSRAM;
  gameboy.openRTC = openRTC;
  gameboy.start();
  run();
}

function run(): void {
  //debugLog('This is run')
  if (gameBoyEmulatorInitialized()) {
    if (!gameBoyEmulatorPlaying()) {
      gameboy!.stopEmulator &= 1;
      cout('Starting the iterator.', 0);
      let dateObj = new Date(); // The line is changed for benchmarking.
      gameboy!.firstIteration = dateObj.getTime();
      gameboy!.iterations = 0;
    } else {
      cout('The GameBoy core is already running.', 1);
    }
  } else {
    cout('GameBoy core cannot run while it has not been initialized.', 1);
  }
}

function pausePlay(): void {
  if (gameBoyEmulatorInitialized()) {
    if (gameBoyEmulatorPlaying()) {
      clearLastEmulation();
    } else {
      cout('GameBoy core has already been paused.', 1);
    }
  } else {
    cout('GameBoy core cannot be paused while it has not been initialized.', 1);
  }
}

function clearLastEmulation(): void {
  if (gameBoyEmulatorInitialized() && gameBoyEmulatorPlaying()) {
    gameboy!.stopEmulator |= GBEMU_2;
    cout('The previous emulation has been cleared.', 0);
  } else {
    cout('No previous emulation was found to be cleared.', 0);
  }
}

function openSRAM(filename: string): number[] {
  return [];
}

function openRTC(filename: string): number[] {
  return [];
}

function gameBoyEmulatorInitialized(): boolean {
  return typeof gameboy === 'object' && gameboy !== null;
}

function gameBoyEmulatorPlaying(): boolean {
  return (gameboy!.stopEmulator & GBEMU_2) === 0;
}

//The emulator will call this to sort out the canvas properties for (re)initialization.
function initNewCanvas(): void {
  if (gameBoyEmulatorInitialized()) {
    gameboy!.canvas!.width = gameboy!.canvas!.clientWidth;
    gameboy!.canvas!.height = gameboy!.canvas!.clientHeight;
  }
}

// Start of realtime.js file.
// ROM code from Public Domain LPC2000 Demo 'realtime' by AGO.

let gameboyRom =
  'r+BPyZiEZwA+AeBPySAobeEq6gAgKlYj5WJv6SRmZjjhKuXqACDJ/////////////////////////////////xgHZwCYhGcA2fX6/3/1xdXlIRPKNgHN9f/h0cHx6gAg+hLKtyAC8cnwgLcoF/CC7hjgUT6Q4FOv4FLgVOCAPv/gVfHZ8IG3IALx2fBA7gjgQA8PD+YB7gHgT/CC4FHuEOCCPojgU6/gUuBU4IE+/uBV4ID6NMs86jTL8dkKCgoKbWFkZSBieSBhZ28uIGVtYWlsOmdvYnV6b3ZAeWFob28uY29tCnVybDogc3BlY2N5LmRhLnJ1CgoKCv///////wDDSgnO7WZmzA0ACwNzAIMADAANAAgRH4iJAA7czG7m3d3Zmbu7Z2NuDuzM3dyZn7u5Mz5BR08nUyBSRUFMVElNRSCAAAAAAgEDADMBSTQeIUD/y37I8P/1y4fg//BE/pEg+su+8eD/yT7A4EY+KD0g/cnF1eWvEQPK1RITEhMGAyEAyuXFTgYAIWAMCQkqEhMqEhPB4SMFIOrhrwYIzYsU4dHByf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAgMFBggJCwwOEBETFBYXGBobHR4fISIjJSYnKSorLC0uLzAxMjM0NTY3ODg5Ojo7PDw9PT4+Pj8/Pz9AQEBAQEBAQEBAPz8/Pz4+PT08PDs7Ojk5ODc2NTU0MzIxMC8uLCsqKSgmJSQjISAfHRwaGRcWFRMSEA8NCwoIBwUEAgH//fz6+ff29PPx8O7t6+ro5+Xk4uHg3t3c2tnY19bU09LR0M/OzczLysnJyMfGxsXFxMPDw8LCwcHBwcDAwMDAwMDAwMDBwcHBwsLDw8PExcXGxsfIycnKy8zNzs/Q0dLT1NXX2Nna3N3e4OHi5OXn6Onr7O7v8fL09vf5+vz9AAEECRAZJDFAUWR5kKnE4QAhRGmQueQRQHGk2RBJhMEAQYTJEFmk8UCR5DmQ6UShAGHEKZD5ZNFAsSSZEIkEgQCBBIkQmSSxQNFk+ZApxGEAoUTpkDnkkUDxpFkQyYRBAMGESRDZpHFAEeS5kGlEIQDhxKmQeWRRQDEkGRAJBAEAAQQJEBkkMUBRZHmQqcThACFEaZC55BFAcaTZEEmEwQBBhMkQWaTxQJHkOZDpRKEAYcQpkPlk0UCxJJkQiQSBAIEEiRCZJLFA0WT5kCnEYQChROmQOeSRQPGkWRDJhEEAwYRJENmkcUAR5LmQaUQhAOHEqZB5ZFFAMSQZEAkEAQAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAgICAgIDAwMDBAQEBAUFBQUGBgYHBwcICAkJCQoKCgsLDAwNDQ4ODw8QEBEREhITExQUFRUWFxcYGRkaGhscHB0eHh8gISEiIyQkJSYnJygpKisrLC0uLzAxMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1FSU1RVVldZWltcXV9gYWJkZWZnaWprbG5vcHJzdHZ3eXp7fX5/gYKEhYeIiouNjpCRk5SWl5manJ2foKKkpaepqqytr7GytLa3ubu9vsDCxMXHycvMztDS1NXX2dvd3+Hi5Obo6uzu8PL09vj6/P4A//z38Ofcz8CvnIdwVzwfAN+8l3BHHO/Aj1wn8Ld8PwC/fDfwp1wPwG8cx3AXvF8AnzzXcAecL8BP3Gfwd/x/AH/8d/Bn3E/AL5wHcNc8nwBfvBdwxxxvwA9cp/A3fL8AP3y38Cdcj8DvHEdwl7zfAB88V3CHnK/Az9zn8Pf8/wD//Pfw59zPwK+ch3BXPB8A37yXcEcc78CPXCfwt3w/AL98N/CnXA/AbxzHcBe8XwCfPNdwB5wvwE/cZ/B3/H8Af/x38GfcT8AvnAdw1zyfAF+8F3DHHG/AD1yn8Dd8vwA/fLfwJ1yPwO8cR3CXvN8AHzxXcIecr8DP3Ofw9/z/AP/////////////////////+/v7+/v79/f39/fz8/Pz8+/v7+vr6+vn5+fj4+Pf39/b29fX19PTz8/Ly8fHw8PDv7u7t7ezs6+vq6uno6Ofn5uXl5OPj4uHh4N/e3t3c3Nva2djY19bV1NTT0tHQz8/OzczLysnIx8bFxMPCwcDAvr28u7q5uLe2tbSzsrGwr62sq6qpqKalpKOioJ+enZyamZiWlZSTkZCPjYyLiYiHhYSCgYB+fXt6eHd1dHJxcG5sa2loZmVjYmBfXVtaWFdVU1JQTk1LSUhGREJBPz08Ojg2NDMxLy0rKigmJCIgHx0bGRcVExEPDQsJBwUDAf9/Px8PBwMBgEAgEAgEAgEAAQEBAQEBAQEBAQEA//////////////+AEAcAAQABAAEBAAEBAAEA/wD//wD//wD/AP+AKwcBAAEAAQD/AP8A/wD/AP8A/wABAAEAAQCARgcBAQEBAQD//////////////wABAQEBAQGAYQf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+AwODw+Pz+/xEAwAGxwj4E9cU+BfUKbwMKZ37+gCALI34LAiN+AwILGOsahhIDHBwcHPE9IN7BIRAAGVRdPgX1Cm8DCmcalhIjfAILfQIDAx0dHR3xPSDnIRgAGVRd8T0grskRAcAB6cI+BPUKbwMKZ37+gCALI34LAiN+AwILGOs+CvUahhIcHBwc8T0g9CN8Agt9AgMD8T0g0MkgIEZJTExFRCAgIFBPTFlHT05TIEhFTElDT1BURVJJTiBBQ1RJT04gIQDADgpwLHQsGhPWICI2ACwNIPE+oOoQyngBCQDlYmsJVF3hDMYKR3AsdCwaG9YgIjYALA0g8a/qEcrJ+hDK/jDI1gTqEMpHPqCQ/lA4Aj5QDgAM1ggw+3ghAcARBAB3xggZDSD5+hHKg+oRykf+UDgCPlAOAAzWCDD7eC4td9YIGQ0g+ckh9grzMf/PzVABr+Am4P/gD+BD4EL2SOBFPkDgQT4E4AfN9RM+CuoAAA4HeeBwJqCvIstsKPsNIPIh/v8yy30g+wEKABH1/yFpAc3kE+cCAVYAEQDBIVt2zeQTrwYYIWsOzYsUIYsOzaQUxwGwAxEAgCGhF8XlzeQT4cERAIjN5BMhAJgRAwABYMDHcc9yIwUg+BQdIPHN9RMhuxUGAc2WE82JEz5E4EGv4EU+A+D/+z4B6hLK4E0QAAB4zccTBSD6zZATxwEACFkhAIhzIwt4sSD5IQDHPv9FdyRwJCJ3JXclcCwg8x5/IQCYx3PPNgDL1DYIx3PLlCPLVCjuPoABDxARIAAhIpjF5XfL1HfLlDwZDSD1POEswQUg7D486jPLr+o0yz3qL8s+oOCCPgLqG8vNiRM+ROBBr+BFPgPg/68+ACEXyyI+CiI+IHev6h7L4ITgluodyz4B6h/L6g/D6g3KBlARnAjNxAjNcwsBLAHFzTsLzQAJwQt4sSDzzZATxwEACFkhAIhzIwt4sSD5zfUTeQYQIYMOzYsUPv/qKcsGgBGwCM3ECM2JEwEsAcXNbAzNAAnBC3ixIPOv6hLKzZATPpDgU/PHAbADEQCIIaEXzeQTzfUTIQIWBgHNlhPNiRM+ROBBr+BFPgPg//sY/j4D6gAgzcRGBgMhF8t+gCJ+gDwifoB3zckP+jDLb/oxy2fNtgs+AeCB8IG3IPv6Dcq3KAPNcwHJ+h3LBgARTg2Hb2AZKmZvTgkq4ItfKjzgjD1PKuCNe4eHg0cRAMUqEhwFIPp5h4eBRxEAxCoSHAUg+n3qMMt86jHLyfCL4I7wjOCP8I3gkBEAw9XlzcoQ4dHwpeaAEhwBAwAJ8JA94JAg6CEAxQYPKk+gXxq3IB95yzegXxq3IBYqT6BfGrcgD3nLN6BfGrcgBiwsLBhHLOXNyhDwlrcoKwYB8KXGP0/LfygBBcXwpMY/Vx4AzZMOe8H18KPGP1ceAM2TDsHhJCJwGAzhJPCjxj8i8KTGPyIsJRbDBg/wjj3gjsLiCz4C6gAgw1JhfBjcHwAL7mpIYL9vBgMhF8t+gCJ+gDwifoB3zckPIcsNEQDGzf4MI+U+A+oAICEgy83+DPocy9YIb+ocy82vYAYDESDLIWIOxeXVzcoQ4fCjxhQi8KQiNg8jVF3hIyMjwQUg5M3ERsE+AeoAIAr+/ygiEQDGbyYAKRnlAwoDbyYAKRleI1bhKmZvxc0xHMwAQMEY2T4B4IHwgbcg+8l+PMjl1c3KEAYB8KVPy38oAQXF8KTLf/UoAi88Vx4AzZMO8XsgAi88xn/B9fCjy3/1KAIvPFceAM2TDvF7KAIvPMZ/wdESE3gSE+EjIyMYsFANAgAIDAYCRCgoFANEKAAUE0QAABQSRAAoFAJVKCjsA1UoAOwTVQAA7BJVACjsAAAEBQAAAAEFAAEBAwIGAQEDBwYCAgAHAwICAAcEAwMBAgYDAwEFBgQEAAECBAQAAwIFBQQFBgUFBAcGMgAAzgAAADIAAM4AAAAyAADOKAAAHhEAChEAAAAACu8AHu8AFAAKFAD2FAAPCgAF6AAC4gAQ3gAQ4gD+CgD74g4C3Q4C4QAC4vIC3fIC4AAM4PsM4PsQ4/sJ3fsJ/wABAQICAwMEBAUFAAAGAQYCBgMGBAYFBgAHAQcCBwMHBAcFBwYICQoKCwsMDA0NDgoPDxAQEQoSEhMTERQVFRYVFxUYCBkIGggb/yAAD/AbD/DlD/9//3+XEQAAAGD/f5cRAAAYAP9/lxEAAIB8lxH/f/9/QHz/f18IAADLI8sSeC9HeS9PAyEAAH2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEssoyxkJ0BPJ+hfLJgJvfuCcLzzgnn3GQG9+4Jvgn6/gmOCZ4JrgneChPkDgl/oYy29OfcZAb0bFeOCgeeCizdMQ8KPgpvCk4KnwpeCsr+Cg4KI+QOChzdMQ8KPgp/Ck4KrwpeCtwXkvPOCgr+CheOCizdMQ8KPgmfCk4JzwpeCf8Kbgl/Cp4JrwrOCd8KfgmPCq4JvwreCe+hnLJgJvTn3GQG9GxXjgoHkvPOChr+CizdMQ8KPgpvCk4KnwpeCswXngoHjgoa/gos3TEPCj4KfwpOCq8KXgra/goOChPkDgos3TEPCj4JnwpOCc8KXgn/Cm4JfwqeCa8KzgnfCn4JjwquCb8K3gnskq4KAq4KEq4KLwl1/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jhf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CZX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KPwml/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jtf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CcX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KTwnV/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8J5f8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CfX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KXJ9T6D4EDxyfWv4EDxyfXF1eXHKv7/KFD+FiAaTiMqh4eHVF1vJgApKXgGmAlHelRne11vGNzGYBLPeBIcGNN2ACETyjQ1KPc1yfvFBmR2AAUg+8HJ+3YABSD7yfXF1eUqEhMLeLEg+OHRwfHJxeUBAKAhAMDNAxThwcnF5XEjBSD74cHJxdXlAQCAIZXKzQMU4dHBycXV5a/qFcuwIAwaEyIaEzIEDXjqFcvlxRq+EyAPIxq+IAkTIw0gCMHhGBkrGyMjBSDmecFPBBoTIhoTIiEVyzThDSDS+hXL4dHBydVfzXIUuzD60cnF9cH6FMrLD6mAR/CLkR+AR/AFqOoUysHJ9cXltxcXF/aA4Ggq4GkFIPo+5OBH4cHxyfXF5bcXFxf2gOBqKuBrBSD6PuTgSOBJ4cHxyT4Q4ADwAC/LN+bwRz4g4ADwAC/mD7DqFsvJzyEAgK8GIE8+CCINIPwFIPnHIQCABiBPIg0g/AUg+cnFzQMVSs0eFcHJxc0RFUjNGRVLzSMVwcnFBgHNKxXBycUGABj2xQYDGPHFBgLNKxXByfXlh4eAJsBvceHxyfXlh4cmwG9GI04jXiNW4fHJ9cXV5eCDKjzK8BPWIF/wg835FF95xghPezwY6PXF1eXF1c13FdHBex4FIS3LGNUBKssR8NjNlRURGPzNlRURnP/NlRUR9v/NlRUR//8+LzwZOPwCA3ovV3svXxMZyTAwRlBT/zAwUE5UU/8wMExJTkVT/xYFB1dFTENPTUUgVE8WBQgtUkVBTFRJTUUtFgAJREVNTyBNQURFIEVTUEVDSUFMTFkWAQpGT1IgTENQJzIwMDAgUEFSVFn/FgAAR1JFRVRJTlg6ICAgICAgICAgICAWAAFEU0MsUEFOLFNBQixGQVRBTElUWRYAAkpFRkYgRlJPSFdFSU4sSUNBUlVTFgADRE9YLFFVQU5HLEFCWVNTICAgICAWAAQgICAgICAgICAgICAgICAgICAgIBYABUNSRURJVFM6ICAgICAgICAgICAgFgAGQUxMIEdGWCZDT0RFIEJZIEFHTyAWAAdIRUxJQ09QVEVSIDNEIE1PREVMIBYACENSRUFURUQgQlkgQlVTWSAgICAgFgAJICAgICAgICAgICAgICAgICAgICAWAApVU0VEIFNPRlRXQVJFOiAgICAgIBYAC1JHQkRTLE5PJENBU0gsRkFSICAgFgAMICAgICAgICAgICAgICAgICAgICAWAA1DT05UQUNUOiAgICAgICAgICAgIBYADkdPQlVaT1ZAWUFIT08uQ09NICAgFgAPSFRUUDovL1NQRUNDWS5EQS5SVSAWABAgICAgICAgICAgICAgICAgICAgIBYAEVNFRSBZT1UgT04gR0JERVYyMDAw/wAAAAAAAAAAAAAAAAAAAAAICBwUHBQ4KDgoMDBwUCAgKCh8VHxUKCgAAAAAAAAAABQUPip/QT4qfFT+gnxUKCgICDw0fkL8rP6Cfmr8hHhYJCR+Wn5SPCR4SPyU/LRISBgYPCR+Wjwkflr8tH5KNDQQEDgocFAgIAAAAAAAAAAABAQOChwUOCg4KDgoHBQICBAQOCgcFBwUHBQ4KHBQICAAABQUPio8NH5CPCx8VCgoAAAICBwUPDR+QjwsOCgQEAAAAAAAAAAAEBA4KHBQcFAAAAAAAAB8fP6CfHwAAAAAAAAAAAAAAAAwMHhIeEgwMAQEDgoeEjwkeEjwkOCgQEAYGDwkflr+qv6q/LR4SDAwGBg8JHxUPDQ4KHxs/oJ8fBwcPiJ+Wjw0eEj8vP6CfHwcHD4iflo8NE5K/LR4SDAwJCR+Wn5afFT8tP6CfGwQEBwcPiJ8XPyEfnr8tHhIMDAYGDwkeFj8pP66/LR4SDAwPDx+Qv66XFQ4KHBQcFAgIBwcPiJ+Wjwkflr8tPiIcHAcHD4iflr+sn5KfHT4iHBwAAAAAAgIHBQICBAQOCgQEAAACAgcFAgIEBA4KDgocFAAAAAAHBQ4KHBQcFA4KAAAAAAAADw8fkJ8fPyEeHgAAAAAAAA4KBwUHBQ4KHBQAAAYGDwkflr8tHhoEBA4KBAQHBw+In5a/rL8pPi4+IhwcBwcPiJ+Wv66/oL+uvy0SEg4OHxEflr8pP6a/LT4iHBwHBw+In5a5qbgoP6y/IxwcDAweEh8VH5a7qr+uvyEeHgcHD4ifFx8RHhY/Lz+gnx8HBw+Inxc/IT4uOCg4KBAQBwcPiJ+Wvy8/qL+uvyEeHgkJH5a/rr+gv66/LT8tEhIPDx+QjwsOChwUHhY/IR4eDw8fkI+Og4KXFT8tHhIMDAkJH5afFR+Qv66/LT8tEhIICBwUHBQ4KDkpP66fEQ4OCgofFR+Qv6q/rr8tPy0SEgkJH5a/pr+qv6y7qr8tEhIHBw+In5a7qruqvy0+IhwcBwcPiJ+Wv66/IT4uOCgQEAcHD4iflr+uv6q/LT+inZ2HBw+In5a/LT4iPy0/LRISBwcPiJ8XP6Cfnr8tPiIcHB8fP6CfGw4KHBQcFBwUCAgJCR+Wn5a7qruqvy0eEgwMERE7qruqnxUfFR4SHBQICAkJH5aflr+uv6q/KR8VCgoJCR+WnxUOCg8JH5a/LRISCQkflr8tPy0eEhwUHBQICA8PH5C/LT46Dwsflr8hHh4HBw+IjwsOChwUHhYfEQ4OEBA4KDwkHhIPCQeEg4KBAQ4OHxEPDQcFDgoeGj4iHBwGBg8JH5a7qpERAAAAAAAAAAAAAAAAAAAAAB8fP6CfHx81rdPfJJne5X1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEeRcvT/F5MAIvPIVvJrcBAAA+t7zLEbrLED6/vcsRu8sQPj+8P8sRuj/LEL0/yxG7P8sQeLHIeKHAebcgB3xiV31rX3jLH9L/HD5AlU97lW96lPUwAi88R6/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYV5Fy9P8XkwAi88hGcuQMMxHMsf0pcdPkCUT3qUZ3uV9TACLzxHr8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhHkXL0/xeTACLzyFbyZAwzEcyx/SoRt91r9PfZNvepT1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFeRcvT/F5MAIvPIRnLr/DMRz//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3q8MAVUZ3tdb3u90pdAfZNPepRfkTA+V3nLPy88g+CDPn+R5YdPbyYARCkpKQkBkVIJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMl5S1+RV3nLPy88g+CDPneR5YdPbyYARCkpKQkBklsJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMmVT3qUX5EwPld5yz8vPIPggz5/keWHT28mAEQpKSkJAR9BCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJeUtfkVd5yz8vPIPggz53keWHT28mAEQpKSkJASBKCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkyX6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALMl+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASXJfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsyf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wHRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyIxDsrh+eEWwxgNIf3Er+oLyuoMyiwsLPCPPcjgj14sGrcqKPDGeeCT+g3Ktygm+gvKPP4DIAI+AeoLyiAH+gzKPOoMyvoMyl8WyvCT1nkSe8bH4JMqTypHKuUmxl+Hh4M8PG8qX1Z5h4eBPDxveE4sh4eARjw8bypmb3y6OAViV31rX3y4OAVgR31pT3q4OAVQR3tZT3iU4JR8h+CV5dXFr+CSzUpifeCS0eHVzUpi0eE+AeCSzUpi8JRfPniTZy5Hr8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdxkBnCA7KMQDC5fCVb8l7vTBVfZNPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAfdiCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQH4ZwnB5SbC8JJveAaAyZVPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAalsCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQGqcQnB5SbC8JJveAaAyYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNyXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDcmDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDMlxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggzJxg+Hh+oawXovpl96obMiei+mX3qgszIkeRgAInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQW/8n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+qqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINnMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBCqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlUC4XIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7LCwly2XIJGjJycnJydE+t5LI4IXmB8RSRPCFHx8focjlzTJE4XkicCwicCwicCwicCwicCwicCwicCwicCzJ+ABUXWhHeZAfyx1nATNZCfCCMQCv/qAoAzEAvwH/AOlHPgeQVF1HDjOvyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxlHIbRXCeViaz7/AQ8Ayfoay2/6G8uFZ/4UIAU+/y0YBtbsIAU8LOoby3zqGsvNr2AhlEbNyhDwpMagV/Cjxn9f1SGXRs3KEPCkxqBn8KPGf2/RzTEcKAsf2hhZH9oYWcPERny6OAViV31rX+XNmkbh1Xu90sxFe9ZA4Ih9k0884Il6lF/ghjzgij2RMGvgh3nLPy88g+CF8IIBDwBvVHzWQBfLN6GFZ3rmBxdvGAjwij3KAETgivCJX/CGV/CFGASCHSgLy38g+Ffwh4LghR3NYkUY2nvgifCIg1/l5gf2CG8mB1Z7aB8fHx/LHR/LHeYDxkBnrx7/6XnghpPgh3vLPy88geCF8IIBDwBvVHzWQBfLN6GFZ3rmBxdv8Ilf8IZX8IXLfyAHV/CHgh0YAYLghc1iRfCKPcoAROCKGN171kDgiHuVTzzgiXqUX+CGPOCKPZEwa+CHecs/LzyD4IXwggEPAG9UfNZAF8s3oYVneuYHF28YCPCKPcoAROCK8Ilf8IZX8IUYBIIdKAvLfyD4V/CHguCFHc0qRhjae+CJ8IiTX+XmB/YQbyYHVntoHx8fH8sdH8sd5gPGQGc+/1jpeeCGk+CHe8s/LzyB4IXwggEPAG9UfNZAF8s3oYVneuYHF2/wiV/whlfwhct/IAdX8IeCHRgBguCFzSpG8Io9ygBE4IoY3UYAALoAAHzWQMhPHx8f5h9HeeYHKAsE/gUwBvUhylblBT4PkCHJRoRn5fCCZ69vyfCCZ69vIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIsnxAQ8APcqEVz0odj0oOj0idwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkid8kicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAloyfgAVF3wgjEAr/6gKAMxAL8B/wDFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcVia/nJJgJ+4JovPOCYfcZAb37gl+Cbr+CZ4JzgneCePkDgn8n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Aw==';
// End of realtime.js file.@

type TNextArray = Int8Array | Uint8Array | Int32Array | Float32Array;

class ArrayObject {
  array: TNextArray = new Int32Array();
}

function debugLog(str: string): void {
  let isLog = false;
  if (isLog) {
    print(str);
  }
}

declare interface ArkTools {
  timeInUs(args: number): number;
}

function gbemuRunIteration(): void {
  let start = ArkTools.timeInUs();
  let benchmark = new Benchmark();
  benchmark.setupGameboy();
  for (let i = 0; i < GBEMU_20; ++i) {
    benchmark.runGameboy();
  }
  benchmark.tearDownGameboy();
  let end = ArkTools.timeInUs();
  print('gbemu: ms = ' + String((end - start) / GBEMU_1000));
}

let loopCountForPreheat = 1;
for (let i = 0; i < loopCountForPreheat; i++) {
  gbemuRunIteration();
}

ArkTools.waitAllJitCompileFinish();

gbemuRunIteration();
